Pola jawne: val — Słowo kluczowe
Słowo val
kluczowe służy do deklarowania lokalizacji do przechowywania wartości w klasie lub typie struktury bez inicjowania. Lokalizacje magazynu zadeklarowane w ten sposób są nazywane jawnymi polami. Innym zastosowaniem słowa kluczowego val
jest połączenie ze słowem kluczowym w member
celu zadeklarowania automatycznie zaimplementowanej właściwości. Aby uzyskać więcej informacji na temat automatycznie zaimplementowanych właściwości, zobacz Właściwości.
Składnia
val [ mutable ] [ access-modifier ] field-name : type-name
Uwagi
Typowym sposobem definiowania pól w klasie lub typie struktury jest użycie let
powiązania. Jednak let
powiązania muszą być inicjowane jako część konstruktora klasy, który nie zawsze jest możliwy, niezbędny lub pożądany. Możesz użyć słowa kluczowego val
, jeśli chcesz, aby pole było niezainicjowane.
Jawne pola mogą być statyczne lub niestatyczne. Modyfikator dostępu może mieć public
wartość , private
lub internal
. Domyślnie jawne pola są publiczne. Różni się to od let
powiązań w klasach, które są zawsze prywatne.
Atrybut DefaultValue jest wymagany dla jawnych pól w typach klas, które mają konstruktor podstawowy. Ten atrybut określa, że pole jest inicjowane do zera. Typ pola musi obsługiwać inicjowanie zerowe. Typ obsługuje inicjowanie zerowe, jeśli jest to jeden z następujących elementów:
- Typ pierwotny, który ma wartość zero.
- Typ, który obsługuje wartość null, jako wartość normalną, jako nietypową wartość lub jako reprezentację wartości. Obejmuje to klasy, krotki, rekordy, funkcje, interfejsy, typy referencyjne platformy .NET,
unit
typ i typy unii dyskryminowanej. - Typ wartości platformy .NET.
- Struktura, której wszystkie pola obsługują domyślną wartość zero.
Na przykład niezmienne pole o nazwie someField
ma pole zapasowe w skompilowanej reprezentacji platformy .NET o nazwie someField@
i uzyskujesz dostęp do przechowywanej wartości przy użyciu właściwości o nazwie someField
.
W przypadku pola modyfikowalnego skompilowana reprezentacja platformy .NET jest polem .NET.
Ostrzeżenie
Przestrzeń nazw System.ComponentModel
programu .NET Framework zawiera atrybut o tej samej nazwie. Aby uzyskać informacje o tym atrybucie, zobacz DefaultValueAttribute.
Poniższy kod przedstawia użycie jawnych pól i, dla porównania, let
powiązanie w klasie, która ma konstruktor podstawowy. Należy pamiętać, że let
pole myInt1
-bound jest prywatne. let
Jeśli pole myInt1
-bound jest przywołyane z metody składowej, identyfikator this
własny nie jest wymagany. Jednak jeśli odwołujesz się do jawnych pól myInt2
i myString
, wymagany jest identyfikator własny.
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)
Wynik jest następujący:
11 12 abc
30 def
Poniższy kod przedstawia użycie jawnych pól w klasie, która nie ma konstruktora podstawowego. W takim przypadku DefaultValue
atrybut nie jest wymagany, ale wszystkie pola muszą zostać zainicjowane w konstruktorach zdefiniowanych dla typu.
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)
Wynik to 35 22
.
Poniższy kod przedstawia użycie jawnych pól w strukturze. Ponieważ struktura jest typem wartości, automatycznie ma konstruktor bez parametrów, który ustawia wartości pól na zero. W związku z tym DefaultValue
atrybut nie jest wymagany.
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)
Wynik to 11 xyz
.
Uważaj, jeśli zamierzasz zainicjować strukturę przy mutable
użyciu pól bez mutable
słowa kluczowego, przypisania będą działać na kopii struktury, która zostanie odrzucona bezpośrednio po przypisaniu. W związku z tym struktura nie ulegnie zmianie.
[<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
Jawne pola nie są przeznaczone do rutynowego użycia. Ogólnie rzecz biorąc, jeśli to możliwe, należy użyć let
powiązania w klasie zamiast jawnego pola. Jawne pola są przydatne w niektórych scenariuszach współdziałania, takich jak w przypadku konieczności zdefiniowania struktury, która będzie używana w wywołaniu platformy do natywnego interfejsu API lub w scenariuszach międzyoperacyjności modelu COM. Aby uzyskać więcej informacji, zobacz Funkcje zewnętrzne. Inną sytuacją, w której może być konieczne jawne pole, jest praca z generatorem kodu języka F#, który emituje klasy bez konstruktora podstawowego. Jawne pola są również przydatne w przypadku zmiennych statycznych wątków lub podobnych konstrukcji. Aby uzyskać więcej informacji, zobacz System.ThreadStaticAttribute
.
Gdy słowa kluczowe member val
są wyświetlane razem w definicji typu, jest to definicja automatycznie zaimplementowanej właściwości. Aby uzyskać więcej informacji, zobacz Właściwości.