Eigenschaften (F#)
Eigenschaften sind Member, die einem Objekt zugeordnete Werte darstellen.
// Property that has both get and set defined.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with [accessibility-modifier] get() =
get-function-body
and [accessibility-modifier] set parameter =
set-function-body
// Alternative syntax for a property that has get and set.
[ attributes-for-get ]
[ static ] member [accessibility-modifier-for-get] [self-identifier.]PropertyName =
get-function-body
[ attributes-for-set ]
[ static ] member [accessibility-modifier-for-set] [self-identifier.]PropertyName
with set parameter =
set-function-body
// Property that has get only.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName =
get-function-body
// Alternative syntax for property that has get only.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with get() =
get-function-body
// Property that has set only.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with set parameter =
set-function-body
// Automatically implemented properties.
[attributes ]
[ static ] member val [accessibility-modifier ] PropertyName = initialization-expression [ with get, set ]
Hinweise
Eigenschaften stellen die Hat-Beziehung in der objektorientierten Programmierung dar, d. h. Daten, die Objektinstanzen oder, bei statischen Eigenschaften, dem Typ zugeordnet sind.
Sie können Eigenschaften in zwei Arten, abhängig, ob Sie explizit den zugrunde liegenden Wert (auch als "Sicherungsspeicher" bezeichnet) für die Eigenschaft festlegen möchten oder wenn Sie zulassen möchten, den Sicherungsspeicher für Sie automatisch generiert den Compiler deklarieren.Im Allgemeinen sollten Sie die explizitere Wenn die Eigenschaft eine nicht-triviale Implementierung sowie die automatische Art verwenden, wenn die Eigenschaft nur ein einfacher Wrapper für einen Wert oder Variable ist.Um eine Eigenschaft explizit zu deklarieren, verwenden Sie die member Schlüsselwort.Auf diese deklarative Syntax folgt die Syntax, die die get-Methode und die set-Methode, auch als Accessoren bezeichnet, angibt.Die verschiedenen Formen der expliziten Syntax, die im Abschnitt "Syntax" sind für Lese-/Schreibzugriff, schreibgeschützt und nur-schreiben-Eigenschaften verwendet.Für schreibgeschützte Eigenschaft definieren Sie nur eine get-Methode, und für lesegeschützte Eigenschaften definieren Sie nur eine set-Methode.Wenn eine Eigenschaft über den get-Accessor und den set-Accessor verfügt, können Sie mit der alternativen Syntax Attribute und Zugriffsmodifizierer angeben, die für jeden Accessor unterschiedlich sind, wie im folgenden Code gezeigt.
// A read-only property.
member this.MyReadOnlyProperty = myInternalValue
// A write-only property.
member this.MyWriteOnlyProperty with set (value) = myInternalValue <- value
// A read-write property.
member this.MyReadWriteProperty
with get () = myInternalValue
and set (value) = myInternalValue <- value
Für Lese-/Schreibeigenschaften, die sowohl über eine get-Methode als auch eine set-Methode verfügen, kann die Reihenfolge von get und set umgekehrt werden.Alternativ können Sie statt der kombinierten Syntax die Syntax für die ausschließliche Verwendung von get und die Syntax für die ausschließliche Verwendung von set bereitstellen.Dies vereinfacht bei Bedarf das Auskommentieren der einzelnen get-Methode oder set-Methode.Diese Alternative zur kombinierten Syntax wird im folgenden Code veranschaulicht.
member this.MyReadWriteProperty with get () = myInternalValue
member this.MyReadWriteProperty with set (value) = myInternalValue <- value
Private Werte, die die Daten für Eigenschaften enthalten, werden als Sicherungsspeicher bezeichnet.Damit den Compiler den Sicherungsspeicher automatisch zu erstellen, verwenden Sie die Schlüsselwörter member val, die Self-Identifier weglassen, dann geben Sie einen Ausdruck zum Initialisieren der Eigenschaft.Wenn die Eigenschaft auf änderbar sein, enthalten with get, set.Beispielsweise enthält der folgenden Klassentyp zwei automatisch implementierte Eigenschaften. Property1ist schreibgeschützt und wird auf den primären Konstruktor bereitgestellten Argument initialisiert und Property2 ist eine festlegbare Eigenschaft, die auf eine leere Zeichenfolge initialisiert:
type MyClass(property1 : int) =
member val Property1 = property1
member val Property2 = "" with get, set
Automatisch implementierte Eigenschaften sind Teil der Initialisierung eines Typs, so dass sie vor anderen Memberdefinitionen, genau wie einbezogen werden müssen, let Bindungen und do Bindungen in einer Typdefinition.Beachten Sie, dass der Ausdruck, der eine automatisch implementierte Eigenschaft initialisiert wird nur ausgewertet, bei der Initialisierung und nicht jedes Mal die Eigenschaft zugegriffen wird.Dieses Verhalten ist im Gegensatz zu dem Verhalten einer explizit implementierte Eigenschaft.Das effektiv bedeutet, dass der Code diese Eigenschaften zu initialisieren, wird der Konstruktor einer Klasse hinzugefügt.Betrachten Sie den folgenden Code, der diese Differenz zeigt:
type MyClass() =
let random = new System.Random()
member val AutoProperty = random.Next() with get, set
member this.ExplicitProperty = random.Next()
let class1 = new MyClass()
printfn "class1.AutoProperty = %d" class1.AutoProperty
printfn "class1.AutoProperty = %d" class1.AutoProperty
printfn "class1.ExplicitProperty = %d" class1.ExplicitProperty
printfn "class1.ExplicitProperty = %d" class1.ExplicitProperty
Output
Die Ausgabe des obigen Codes zeigt, dass der Wert der AutoProperty unverändert, wenn aufgerufen, während der ExplicitProperty jedes Mal ändert, wenn es aufgerufen wird.Dies zeigt, dass der Ausdruck für eine automatisch implementierte Eigenschaft nicht jedes Mal ausgewertet wird, wie die Getter-Methode für die explizite-Eigenschaft ist.
Vorsicht |
---|
Es gibt einige Bibliotheken wie gerade Basisklassenkonstruktoren benutzerdefinierte Operationen durchführen, die auch die Initialisierung automatisch funktionieren nicht mit Entity Framework (System.Data.Entity) Eigenschaften implementiert.Verwenden Sie in diesen Fällen explizite Eigenschaften. |
Eigenschaften können Member von Klassen, Strukturen, Unterscheidungs-Unions, Datensätzen, Schnittstellen und Typerweiterungen sein und auch in Objektausdrücken definiert werden.
Auf Eigenschaften können Attribute angewendet werden.Schreiben Sie das Attribut in einer eigenen Zeile vor der Eigenschaft, um ein Attribut auf eine Eigenschaft anzuwenden.Weitere Informationen finden Sie unter Attribute (F#).
Eigenschaften sind standardmäßig öffentlich.Auf Eigenschaften können auch Zugriffsmodifizierer angewendet werden.Fügen Sie zum Anwenden eines Zugriffsmodifizierers diesen direkt vor dem Namen der Eigenschaft hinzu, wenn er sowohl für die get-Methode als auch die set-Methode gelten soll. Fügen Sie ihn vor dem get-Schlüsselwort und dem set-Schlüsselwort hinzu, wenn für jeden Accessor ein anderer Zugriff erforderlich ist.Als accessibility-modifier kann einer der folgenden Modifizierer verwendet werden: public, private, internal.Weitere Informationen finden Sie unter Zugriffssteuerung (F#).
Eigenschaftenimplementierungen werden jedes Mal ausgeführt, wenn auf eine Eigenschaft zugegriffen wird.
Statische und Instanzeigenschaften
Eigenschaften können statische Eigenschaften oder Instanzeigenschaften sein.Statische Eigenschaften können ohne Instanz aufgerufen werden, und sie werden für dem Typ zugeordnete Werte, nicht für einzelne Objekte verwendet.Für statische Eigenschaften auslassen der Self-Identifier.Das Self-Identifier ist für Instanzeigenschaften erforderlich.
Die folgende statische Eigenschaftendefinition basiert auf einem Szenario, in dem das statische Feld myStaticValue der Sicherungsspeicher für die Eigenschaft ist.
static member MyStaticProperty
with get() = myStaticValue
and set(value) = myStaticValue <- value
Eigenschaften können auch arrayähnliche Eigenschaften sein. In diesem Fall werden sie als indizierte Eigenschaften bezeichnet.Weitere Informationen finden Sie unter Indizierte Eigenschaften (F#).
Typanmerkungen für Eigenschaften
Häufig verfügt der Compiler über ausreichende Informationen, um den Typ einer Eigenschaft vom Typ des Sicherungsspeichers abzuleiten, jedoch können Sie den Typ explizit festlegen, indem Sie eine Typanmerkung hinzufügen.
// To apply a type annotation to a property that does not have an explicit
// get or set, apply the type annotation directly to the property.
member this.MyProperty1 : int = myInternalValue
// If there is a get or set, apply the type annotation to the get or set method.
member this.MyProperty2 with get() : int = myInternalValue
Verwenden von set-Accessoren von Eigenschaften
Sie können mit dem <--Operator Eigenschaften festlegen, die set-Accessoren bereitstellen.
// Assume that the constructor argument sets the initial value of the
// internal backing store.
let mutable myObject = new MyType(10)
myObject.MyProperty <- 20
printfn "%d" (myObject.MyProperty)
Die Ausgabe lautet 20.
Abstrakte Eigenschaften
Eigenschaften können abstrakt sein.Wie bei Methoden bedeutet abstrakt lediglich, dass der Eigenschaft ein virtueller Dispatch zugeordnet ist.Abstrakte Eigenschaften können tatsächlich abstrakt sein, d. h., sie verfügen über keine Definition in der gleichen Klasse.Die Klasse, die eine solche Eigenschaft enthält, ist daher eine abstrakte Klasse.Abstrakt kann auch lediglich bedeuten, dass es sich um eine virtuelle Eigenschaft handelt, und in diesem Fall muss eine Definition in der gleichen Klasse vorhanden sein.Beachten Sie, dass abstrakte Eigenschaften nicht privat sein dürfen, und wenn ein Accessor abstrakt ist, muss der andere Accessor ebenfalls abstrakt sein.Weitere Informationen zu abstrakten Klassen finden Sie unter Abstrakte Klassen (F#).
// Abstract property in abstract class.
// The property is an int type that has a get and
// set method
[<AbstractClass>]
type AbstractBase() =
abstract Property1 : int with get, set
// Implementation of the abstract property
type Derived1() =
inherit AbstractBase()
let mutable value = 10
override this.Property1 with get() = value and set(v : int) = value <- v
// A type with a "virtual" property.
type Base1() =
let mutable value = 10
abstract Property1 : int with get, set
default this.Property1 with get() = value and set(v : int) = value <- v
// A derived type that overrides the virtual property
type Derived2() =
inherit Base1()
let mutable value2 = 11
override this.Property1 with get() = value2 and set(v) = value2 <- v