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
, private
nebo 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 let
pole myInt1
-bound je soukromé. Pokud je let
pole myInt1
vázané na odkaz z členské metody, identifikátor sebe this
není povinný. Pokud ale odkazujete na explicitní pole myInt2
a myString
identifiká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.