Champs explicites : mot clé val (F#)
Le mot clé val est utilisé pour déclarer un champ dans un type de classe ou de structure sans l'initialiser. Les champs déclarés de cette manière sont appelés champs explicites.
[ static ] val [ mutable ] [ access-modifier ] field-name : type-name
Notes
La définition de champs dans un type de classe ou de structure s'effectue généralement à l'aide d'une liaison let. Toutefois, les liaisons let doivent être initialisées dans le cadre du constructeur de classe, ce qui n'est pas toujours possible, nécessaire ou souhaitable. Vous pouvez utiliser le mot clé val pour définir un champ non initialisé.
Les champs explicites peuvent être statiques ou non. access-modifier peut être public, private ou internal. Par défaut, les champs explicites sont publics. Cela diffère des liaisons let dans les classes, qui sont toujours privées.
L'attribut DefaultValue est obligatoire sur les champs explicites dans les types de classe qui ont un constructeur principal. Cet attribut spécifie que le champ est initialisé à zéro. Le type du champ doit prendre en charge l'initialisation à zéro. Un type prend en charge l'initialisation à zéro s'il est l'un des types suivants :
Type primitif qui a une valeur zéro.
Type qui prend en charge une valeur Null, comme valeur normale, comme valeur anormale ou comme représentation d'une valeur. Cela inclut les classes, les tuples, les enregistrements, les fonctions, interfaces, les types référence .NET, le type unit et les types d'union discriminée.
Type valeur .NET.
Structure dont les champs prennent tous en charge une valeur zéro par défaut.
Le code suivant montre l'utilisation de champs explicites et, en guise de comparaison, une liaison let dans une classe avec un constructeur principal. Notez que le champ myInt1 lié à let est privé. Lorsque le champ myInt1 lié à let est référencé à partir d'une méthode membre, l'auto-identificateur this n'est pas obligatoire. Il l'est cependant lorsque vous référencez les champs explicites myInt2 et myString.
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)
La sortie est la suivante :
11 12 abc
30 def
Le code suivant illustre l'utilisation de champs explicites dans une classe qui n'a pas de constructeur principal. Dans ce cas, l'attribut DefaultValue n'est pas obligatoire, mais tous les champs doivent être initialisés dans les constructeurs définis pour le type.
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)
Le résultat est 35 22.
Le code suivant illustre l'utilisation de champs explicites dans une structure. Étant donné qu'une structure est un type valeur, elle a automatiquement un constructeur par défaut qui affecte zéro aux valeurs de ses champs. Par conséquent, l'attribut DefaultValue n'est pas obligatoire.
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)
Le résultat est 11 xyz.
Les champs explicites ne sont pas destinés à une utilisation de routine. En général, lorsque cela est possible, vous devez utiliser une liaison let dans une classe au lieu d'un champ explicite. Les champs explicites sont utiles dans certains scénarios d'interopérabilité, par exemple lorsque vous devez définir une structure qui sera utilisée dans un appel de code non managé à une API native ou dans des scénarios COM Interop. Pour plus d'informations, consultez Fonctions externes (F#). Un champ explicite peut également être nécessaire lorsque vous utilisez un générateur de code F#qui émet des classes sans constructeur principal. Les champs explicites sont également utiles pour les variables statiques de thread ou des constructions semblables. Pour plus d'informations, consultez ThreadStaticAttribute.
Voir aussi
Référence
Liaisons let dans les classes (F#)