Campi espliciti: parola chiave val (F#)
La parola chiave val viene utilizzata per dichiarare un campo in un tipo di classe o struttura senza inizializzarlo. I campi dichiarati in questo modo sono detti campi espliciti.
[ static ] val [ mutable ] [ access-modifier ] field-name : type-name
Note
La modalità standard per definire campi in un tipo di classe o struttura consiste nell'utilizzare l'associazione let. Le associazioni let devono tuttavia essere inizializzate come parte del costruttore di classe e questa operazione non sempre è possibile, necessaria o appropriata. È possibile utilizzare la parola chiave val quando si desidera un campo non inizializzato.
I campi espliciti possono essere statici o non statici. Il valore di access-modifier può essere public, private o internal. Per impostazione predefinita, i campi espliciti sono pubblici. Questo comportamento è diverso rispetto alle associazioni let nelle classi, che sono sempre private.
L'attributo DefaultValue è obbligatorio nei campi espliciti nei tipi di classe con un costruttore primario. Questo attributo specifica che il campo è inizializzato su zero. Il tipo del campo deve supportare l'inizializzazione su zero. Un tipo supporta l'inizializzazione su zero se è uno dei tipi seguenti:
Un tipo primitivo con un valore zero.
Un tipo che supporta un valore Null, come valore normale, come valore anomalo o come rappresentazione di un valore. Sono inclusi classi, tuple, record, funzioni, interfacce, tipi di riferimento .NET, il tipo unit e i tipi di unioni discriminate.
Un tipo di valore .NET.
Una struttura i cui campi supportano tutti un valore zero predefinito.
Nel codice seguente viene illustrato l'utilizzo di campi espliciti e, per confronto, un'associazione let in una classe che dispone di un costruttore primario. Si noti che il campo con associazione let myInt1 è privato. Quando viene fatto riferimento al campo con associazione let myInt1 da un metodo del membro, l'autoidentificatore this non è richiesto. Quando invece viene fatto riferimento ai campi espliciti myInt2 e myString, l'autoidentificatore è richiesto.
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 è indicato di seguito:
11 12 abc
30 def
Nel codice seguente viene illustrato l'utilizzo di campi espliciti in una classe che non dispone di un costruttore primario. In questo caso, l'attributo DefaultValue non è necessario, 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 l'utilizzo di campi espliciti in una struttura. Poiché una struttura è un tipo di valore, dispone automaticamente di un costruttore predefinito che imposta i valori dei campi su zero. L'attributo DefaultValue non è pertanto necessario.
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.
I campi espliciti non sono destinati all'utilizzo comune. In genere, se possibile, è consigliabile utilizzare un'associazione let in una classe, anziché un campo esplicito. I campi espliciti sono utili in determinati scenari di interoperabilità, ad esempio quando è necessario definire una struttura che verrà utilizzata in una chiamata platform invoke a un'API nativa o in scenari di interoperabilità COM. Per ulteriori informazioni, vedere Funzioni esterne (F#). Un'altra situazione in cui un campo esplicito potrebbe essere necessario si verifica quando si utilizza un generatore di codice F# che genera classi senza un costruttore primario. I campi espliciti sono utili anche per le variabili statiche a livello di thread o per costrutti simili. Per ulteriori informazioni, vedere ThreadStaticAttribute.
Vedere anche
Riferimenti
Associazioni let nelle classi (F#)