Explicitní pole: Klíčové slovo val

Klíčové val slovo se používá k deklaraci umístění pro uložení hodnoty v typu třídy nebo struktury bez inicializace. Umístění úložiště deklarovaná tímto způsobem se nazývají explicitní pole. Další použití klíčového val slova je ve spojení s klíčovým slovem member k deklaraci automaticky implementované vlastnosti. Další informace o automaticky implementovaných vlastnostech naleznete v tématu Vlastnosti.

Syntaxe

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

Poznámky

Obvyklým způsobem definování polí v typu třídy nebo struktury je použití vazby let . let Vazby však musí být inicializovány jako součást konstruktoru třídy, což není vždy možné, nezbytné nebo žádoucí. Klíčové slovo můžete použít val , pokud chcete pole, které není inicializované.

Explicitní pole můžou být statická nebo ne statická. Modifikátor přístupu může být public, privatenebo internal. Ve výchozím nastavení jsou explicitní pole veřejná. To se liší od let vazeb ve třídách, které jsou vždy soukromé.

Atribut DefaultValue je vyžadován u explicitních polí v typech tříd, které mají primární konstruktor. Tento atribut určuje, že pole je inicializováno na nulu. Typ pole musí podporovat inicializaci nulou. Typ podporuje inicializaci nulou, pokud se jedná o jednu z následujících možností:

  • Primitivní typ, který má nulovou hodnotu.
  • Typ, který podporuje hodnotu null, buď jako normální hodnotu, jako neobvyklou hodnotu, nebo jako reprezentaci hodnoty. To zahrnuje třídy, řazené kolekce členů, záznamy, funkce, rozhraní, odkazové typy .NET, unit typ a diskriminované typy sjednocení.
  • Typ hodnoty .NET.
  • Struktura, jejíž pole podporují výchozí nulovou hodnotu.

Například neměnné pole má someField záložní pole v zkompilované reprezentaci s názvem someField@.NET a k uložené hodnotě přistupujete pomocí vlastnosti s názvem someField.

U proměnlivého pole je zkompilovaná reprezentace .NET pole .NET.

Upozorňující

Obor názvů System.ComponentModel rozhraní .NET Framework obsahuje atribut, který má stejný název. Informace o tomto atributu naleznete v tématu DefaultValueAttribute.

Následující kód ukazuje použití explicitních polí a pro porovnání vazby let ve třídě, která má primární konstruktor. Všimněte si, že letpole myInt1 -bound je soukromé. Pokud je letpole myInt1 vázané na odkaz z členské metody, identifikátor sebe this není povinný. Pokud ale odkazujete na explicitní pole myInt2 a myStringidentifikátor sebe sama, je povinný.

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)

Výstup je následující:

11 12 abc
30 def

Následující kód ukazuje použití explicitních polí ve třídě, která nemá primární konstruktor. V tomto případě DefaultValue není atribut povinný, ale všechna pole musí být inicializována v konstruktorech, které jsou definovány pro typ.

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)

Výstup je 35 22.

Následující kód ukazuje použití explicitních polí ve struktuře. Vzhledem k tomu, že struktura je typ hodnoty, má automaticky konstruktor bez parametrů, který nastaví hodnoty jeho polí na nulu. DefaultValue Atribut proto není povinný.

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)

Výstup je 11 xyz.

Pokud budete strukturu inicializovat pomocí mutable polí bez mutable klíčového slova, zadání budou fungovat na kopii struktury, která se zahodí hned po přiřazení. Vaše struktura se proto nezmění.

[<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

Explicitní pole nejsou určená pro rutinní použití. Obecně platí, že pokud je to možné, měli byste místo explicitního pole použít let vazbu ve třídě. Explicitní pole jsou užitečná v určitých scénářích interoperability, například v případě, že potřebujete definovat strukturu, která se použije v volání platformy volání nativního rozhraní API nebo ve scénářích interoperability modelu COM. Další informace naleznete v tématu Externí funkce. Další situace, kdy explicitní pole může být nezbytné, je při práci s generátorem kódu jazyka F#, který generuje třídy bez primárního konstruktoru. Explicitní pole jsou užitečná také pro statické proměnné vlákna nebo podobné konstrukce. Další informace najdete na webu System.ThreadStaticAttribute.

Když se klíčová slova member val zobrazí společně v definici typu, jedná se o definici automaticky implementované vlastnosti. Další informace naleznete v tématu Vlastnosti.

Viz také