Freigeben über


Explizite Felder: Das val-Schlüsselwort (F#)

Das val-Schlüsselwort wird verwendet, um ein Feld in einem Klassen- oder Strukturtyp zu deklarieren, ohne es zu initialisieren. Auf diese Weise deklarierte Felder werden als explizite Felder bezeichnet.

[ static ] val [ mutable ] [ access-modifier ] field-name : type-name

Hinweise

Normalerweise werden Felder in einem Klassen- oder Strukturtyp mit einer let-Bindung definiert. let-Bindungen müssen jedoch als Teil des Klassenkonstruktors initialisiert werden, und dies ist nicht immer möglich, erforderlich oder wünschenswert. Sie können das val-Schlüsselwort verwenden, wenn ein Feld nicht initialisiert werden soll.

Explizite Felder können statisch oder nicht statisch sein. Der access-modifier kann public, private oder internal lauten. Standardmäßig sind explizite Felder öffentlich. let-Bindungen in Klassen sind hingegen immer privat.

Das DefaultValue-Attribut ist in expliziten Feldern von Klassentypen, die über einen primären Konstruktor verfügen, erforderlich. Dieses Attribut gibt an, dass das Feld mit 0 (null) initialisiert wird. Der Typ des Felds muss die Initialisierung mit null (0) unterstützen. Folgende Arten von Typen unterstützen die Initialisierung mit 0 (null):

  • Ein primitiver Typ, der über den Wert 0 (null) verfügt.

  • Ein Typ, der einen NULL-Wert unterstützt, und zwar als normaler Wert, als nicht normaler Wert oder als Darstellung eines Werts. Dies schließt Klassen, Tupel, Datensätze, Funktionen, Schnittstellen, .NET-Verweistypen, den unit-Typ und Unterscheidungs-Union-Typen ein.

  • Ein .NET-Werttyp.

  • Eine Struktur, deren sämtliche Felder den Standardwert 0 (null) unterstützen.

Im folgenden Code werden die Verwendung expliziter Felder und zum Vergleich eine let-Bindung in einer Klasse, die über einen primären Konstruktor verfügt, veranschaulicht. Beachten Sie, dass das Feld myInt1 mit let-Bindung ein privates Feld ist. Wenn eine Membermethode auf das Feld myInt1 verweist, das eine let-Bindung aufweist, ist der Selbstbezeichner this nicht erforderlich. Wenn jedoch auf die expliziten Felder myInt2 und myString verwiesen wird, ist der Selbstbezeichner erforderlich.

type MyType() =
    let mutable myInt1 = 10
    [<DefaultValue>] val mutable myInt2 : int
    [<DefaultValue>] val mutable myString : string
    member this.SetValsAndPrint( i: int, str: string) =
       myInt1 <- i
       this.myInt2 <- i + 1
       this.myString <- str
       printfn "%d %d %s" myInt1 (this.myInt2) (this.myString)

let myObject = new MyType()
myObject.SetValsAndPrint(11, "abc")
// The following line is not allowed because let bindings are private.
// myObject.myInt1 <- 20
myObject.myInt2 <- 30
myObject.myString <- "def"

printfn "%d %s" (myObject.myInt2) (myObject.myString)

Die Ausgabe lautet wie folgt:

11 12 abc

30 def

Im folgenden Code wird die Verwendung von expliziten Feldern in einer Klasse veranschaulicht, die über keinen primären Konstruktor verfügt. In diesem Fall ist das DefaultValue-Attribut nicht erforderlich, jedoch müssen alle Felder in den Konstruktoren initialisiert werden, die für den Typ definiert sind.

type MyClass =
    val a : int
    val b : int
    // The following version of the constructor is an error
    // because b is not initialized.
    // new (a0, b0) = { a = a0; }
    // The following version is acceptable because all fields are initialized.
    new(a0, b0) = { a = a0; b = b0; }

let myClassObj = new MyClass(35, 22)
printfn "%d %d" (myClassObj.a) (myClassObj.b)

Die Ausgabe lautet 35 22.

Im folgenden Code wird die Verwendung von expliziten Feldern in einer Struktur veranschaulicht. Da eine Struktur ein Werttyp ist, verfügt sie automatisch über einen Standardkonstruktor, der die Werte der zugehörigen Felder auf 0 (null) festlegt. Daher ist das DefaultValue-Attribut nicht erforderlich.

type MyStruct =
    struct
        val mutable myInt : int
        val mutable myString : string
    end

let mutable myStructObj = new MyStruct()
myStructObj.myInt <- 11
myStructObj.myString <- "xyz"

printfn "%d %s" (myStructObj.myInt) (myStructObj.myString)

Die Ausgabe lautet 11 xyz.

Explizite Felder sind nicht für die regelmäßige Verwendung vorgesehen. Verwenden Sie in einer Klasse nach Möglichkeit statt eines expliziten Felds eine let-Bindung. Explizite Felder sind in bestimmten Interoperabilitätsszenarios hilfreich, z. B. wenn Sie eine Struktur definieren müssen, die in einem Plattformaufruf einer systemeigenen API verwendet wird, oder in COM-Interop-Szenarios. Weitere Informationen finden Sie unter Externe Funktionen (F#). Ein explizites Feld ist möglicherweise auch erforderlich, wenn Sie mit einem F#-Code-Generator arbeiten, der Klassen ohne primären Konstruktor ausgibt. Explizite Felder sind auch für threadstatische Variablen oder ähnliche Konstrukte sinnvoll. Weitere Informationen finden Sie unter ThreadStaticAttribute.

Siehe auch

Referenz

let-Bindungen in Klassen (F#)

Konzepte

Member (F#)