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. Un altro utilizzo della parola chiave val è combinazione con la parola chiave member per dichiarare una proprietà implementata automaticamente. Per ulteriori informazioni sulle proprietà implementate automaticamente, vedere Proprietà (F#).

 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.

Avviso

nota lo spazio dei nomi di .NET Framework System.ComponentModel contiene un attributo con lo stesso nome.Per informazioni su questo attributo, vedere DefaultValueAttribute.

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.

Quando le parole chiave member val vengono visualizzati insieme in una definizione di tipo, è una definizione di una proprietà implementata automaticamente. Per ulteriori informazioni, vedere Proprietà (F#).

Vedere anche

Riferimenti

Proprietà (F#)

Associazioni let nelle classi (F#)

Altre risorse

Membri (F#)