Delen via


Expliciete velden: het trefwoord val

Het val trefwoord wordt gebruikt om een locatie te declareren voor het opslaan van een waarde in een klasse- of structuurtype, zonder deze te initialiseren. Opslaglocaties die op deze manier worden gedeclareerd, worden expliciete velden genoemd. Een ander gebruik van het val trefwoord is in combinatie met het member trefwoord om een automatisch geïmplementeerde eigenschap te declareren. Zie Eigenschappen voor meer informatie over automatisch geïmplementeerde eigenschappen.

Syntaxis

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

Opmerkingen

De gebruikelijke manier om velden in een klasse- of structuurtype te definiëren, is door een let binding te gebruiken. let Bindingen moeten echter worden geïnitialiseerd als onderdeel van de klasseconstructor, die niet altijd mogelijk, noodzakelijk of wenselijk is. U kunt het val trefwoord gebruiken als u een veld wilt dat niet-geïnitialiseerd is.

Expliciete velden kunnen statisch of niet-statisch zijn. De toegangsaanpassing kan , publicprivateof internal. Expliciete velden zijn standaard openbaar. Dit verschilt van let bindingen in klassen, die altijd privé zijn.

Het kenmerk DefaultValue is vereist voor expliciete velden in klassetypen met een primaire constructor. Dit kenmerk geeft aan dat het veld wordt geïnitialiseerd tot nul. Het type veld moet ondersteuning bieden voor nul-initialisatie. Een type ondersteunt nul-initialisatie als dit een van de volgende is:

  • Een primitief type met een nulwaarde.
  • Een type dat een null-waarde ondersteunt, ofwel als een normale waarde, als een abnormale waarde of als een weergave van een waarde. Dit omvat klassen, tuples, records, functies, interfaces, .NET-referentietypen, het unit type en gediscrimineerde samenvoegingstypen.
  • Een .NET-waardetype.
  • Een structuur waarvan alle velden een standaard nulwaarde ondersteunen.

Een onveranderbaar veld met de naam someField heeft bijvoorbeeld een back-upveld in de .NET-gecompileerde weergave met de naam someField@en u opent de opgeslagen waarde met behulp van een eigenschap met de naam someField.

Voor een veranderlijk veld is de gecompileerde .NET-weergave een .NET-veld.

Waarschuwing

De .NET Framework-naamruimte System.ComponentModel bevat een kenmerk met dezelfde naam. Zie DefaultValueAttributevoor meer informatie over dit kenmerk.

De volgende code toont het gebruik van expliciete velden en, ter vergelijking, een let binding in een klasse met een primaire constructor. Houd er rekening mee dat het letveld -gebonden myInt1 privé is. Wanneer er vanuit een lidmethode naar het letveld myInt1 -bound wordt verwezen, is de self-id this niet vereist. Maar wanneer u verwijst naar de expliciete velden myInt2 en myString, is de self-id vereist.

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)

De uitvoer is als volgt:

11 12 abc
30 def

De volgende code toont het gebruik van expliciete velden in een klasse die geen primaire constructor heeft. In dit geval is het DefaultValue kenmerk niet vereist, maar moeten alle velden worden geïnitialiseerd in de constructors die zijn gedefinieerd voor het type.

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)

De uitvoer is 35 22.

De volgende code toont het gebruik van expliciete velden in een structuur. Omdat een structuur een waardetype is, heeft deze automatisch een constructor zonder parameters waarmee de waarden van de velden worden ingesteld op nul. Daarom is het DefaultValue kenmerk niet vereist.

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)

De uitvoer is 11 xyz.

Pas op, als u uw structuur mutable met velden zonder mutable trefwoord gaat initialiseren, werken uw toewijzingen aan een kopie van de structuur die direct na de toewijzing wordt verwijderd. Daarom verandert uw structuur niet.

[<Struct>]
type Foo =
    val mutable bar: string
    member self.ChangeBar bar = self.bar <- bar
    new (bar) = {bar = bar}

let foo = Foo "1"
foo.ChangeBar "2" //make implicit copy of Foo, changes the copy, discards the copy, foo remains unchanged
printfn "%s" foo.bar //prints 1

let mutable foo' = Foo "1"
foo'.ChangeBar "2" //changes foo'
printfn "%s" foo'.bar //prints 2

Expliciete velden zijn niet bedoeld voor routinegebruik. Over het algemeen moet u, indien mogelijk, een let binding in een klasse gebruiken in plaats van een expliciet veld. Expliciete velden zijn handig in bepaalde interoperabiliteitsscenario's, zoals wanneer u een structuur moet definiëren die wordt gebruikt in een aanroep van het platform naar een systeemeigen API of in COM-interop-scenario's. Zie Externe functies voor meer informatie. Een andere situatie waarin een expliciet veld mogelijk nodig is, is wanneer u met een F#-codegenerator werkt die klassen zonder primaire constructor verzendt. Expliciete velden zijn ook handig voor thread-statische variabelen of vergelijkbare constructies. Zie System.ThreadStaticAttribute voor meer informatie.

Wanneer de trefwoorden member val samen worden weergegeven in een typedefinitie, is het een definitie van een automatisch geïmplementeerde eigenschap. Zie Eigenschappen voor meer informatie.

Zie ook