Campi espliciti: parola chiave val
La parola chiave val
viene usata per dichiarare un percorso per archiviare un valore in un tipo di classe o struttura senza inizializzarlo. Le posizioni di archiviazione dichiarate in questo modo sono denominate campi espliciti. Un altro uso della val
parola chiave è in combinazione con la member
parola chiave per dichiarare una proprietà implementata automaticamente. Per altre informazioni sulle proprietà implementate automaticamente, vedere Proprietà.
Sintassi
val [ mutable ] [ access-modifier ] field-name : type-name
Osservazioni:
La modalità standard per definire i campi in un tipo di classe o struttura consiste nell'usare un'associazione let
. Tuttavia, le associazioni let
devono essere inizializzate come parte del costruttore della classe, ma non è sempre possibile, necessario o appropriato. È possibile usare la parola chiave val
quando si desidera un campo non inizializzato.
I campi espliciti possono essere statici o non statici. Il modificatore di accesso può essere public
, private
o internal
. Per impostazione predefinita, i campi espliciti sono pubblici. Questo comportamento è diverso dalle associazioni let
nelle classi, che invece sono sempre private.
L'attributo DefaultValue è obbligatorio nei campi espliciti nei tipi di classe con un costruttore primario. Questo attributo specifica che il campo viene inizializzato su zero. Il tipo del campo deve supportare l'inizializzazione su zero. Un tipo supporta l'inizializzazione su zero se corrisponde a uno dei seguenti tipi:
- Un tipo primitivo con valore pari a zero.
- Un tipo che supporta un valore null come valore normale, come valore anomalo o come rappresentazione di un valore. Questo include classi, tuple, record, funzioni, interfacce, tipi di riferimento .NET, il tipo
unit
e i tipi di unioni discriminati. - Un tipo di valore .NET.
- Una struttura in cui tutti i campi supportano un valore predefinito pari a zero.
Ad esempio, un campo non modificabile chiamato someField
è un campo di supporto nella rappresentazione compilata .NET con il nome someField@
e si accede al valore archiviato usando una proprietà denominata someField
.
Per un campo modificabile, la rappresentazione compilata .NET è un campo .NET.
Avviso
Lo spazio dei nomi System.ComponentModel
.NET Framework contiene un attributo con lo stesso nome. Per altre informazioni sull'attributo, vedere DefaultValueAttribute.
Nel codice seguente viene illustrato l'uso di campi espliciti e, per il confronto, un'associazione let
in una classe che dispone di un costruttore primario. Si noti che il campo associato let
myInt1
è privato. Quando si fa riferimento al campo associato let
myInt1
da un metodo membro, l'autoidentificatore this
non è necessario. Ma quando si fa riferimento ai campi espliciti myInt2
e myString
, l'autoidentificatore è obbligatorio.
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)
L'output è il seguente:
11 12 abc
30 def
Nel codice seguente viene illustrato come usare i campi espliciti in una classe che non dispone di un costruttore principale. In questo caso, l'attributo DefaultValue
non è obbligatorio, ma tutti i campi devono essere inizializzati nei costruttori definiti per il tipo.
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)
L'output è 35 22
.
Nel codice seguente viene illustrato come usare i campi espliciti in una struttura. Poiché una struttura è un tipo valore, ha automaticamente un costruttore senza parametri che imposta i valori dei relativi campi su zero. Pertanto l'attributo DefaultValue
non è obbligatorio.
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)
L'output è 11 xyz
.
Attenzione, se si intende inizializzare la struttura con mutable
campi senza mutable
parola chiave, le assegnazioni funzioneranno su una copia della struttura che verrà rimossa subito dopo l'assegnazione. Pertanto, la struttura non cambierà.
[<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
I campi espliciti non sono destinati all'uso di routine. In generale, quando possibile è consigliabile usare un'associazione let
in una classe anziché un campo esplicito. I campi espliciti sono utili in alcuni scenari di interoperabilità, ad esempio quando è necessario definire una struttura che verrà usata in una chiamata platform invoke per un'API nativa o in scenari di interoperabilità COM. Per altre informazioni, vedere Funzioni esterne. Un'altra situazione in cui un campo esplicito potrebbe essere necessario è quando si lavora con un generatore di codice F# che genera classi senza un costruttore primario. I campi espliciti sono utili anche per le variabili di thread statiche o per costrutti simili. Per ulteriori informazioni, vedere System.ThreadStaticAttribute
.
Quando le parole chiave member val
vengono visualizzate insieme in una definizione di tipo è una definizione di una proprietà implementata automaticamente. Per ulteriori informazioni, vedi Proprietà.