Partager via


Contraintes

Cette rubrique décrit les contraintes que vous pouvez appliquer aux paramètres de type générique pour spécifier les exigences d’un argument de type dans un type ou une fonction générique.

Syntaxe

type-parameter-list when constraint1 [ and constraint2]

Remarques

Il existe plusieurs contraintes différentes que vous pouvez appliquer pour limiter les types qui peuvent être utilisés dans un type générique. Le tableau suivant répertorie et décrit ces contraintes.

Contrainte Syntaxe Description
Contrainte de type paramètre de type :>type Le type fourni doit être égal ou dérivé du type spécifié, ou, si le type est une interface, le type fourni doit implémenter l’interface.
Contrainte Null type-paramètre : null Le type fourni doit prendre en charge la valeur Null. Cela inclut tous les types d’objets .NET, mais pas la liste F#, le tuple, la fonction, la classe, l’enregistrement ou les types union.
Contrainte Not Null paramètre de type : non nul Le type fourni ne doit pas prendre en charge la valeur Null. Cela interdit à la fois les types null annotés et les types qui ont la valeur null comme valeur de représentation (par exemple, le type d’option ou les types définis avec l’attribut AllowNullLiteral). Cette contrainte générique autorise les types valeur, car ceux-ci ne peuvent jamais être null.
Contrainte Membre explicite [(]type-parameter [ou ... ou type-parameter)] : (member-signature) Au moins un des arguments de type fournis doit avoir un membre qui a la signature spécifiée ; non destiné à une utilisation courante. Les membres doivent être définis explicitement sur le type ou une partie d’une extension de type implicite pour être des cibles valides pour une contrainte de membre explicite.
Contrainte de constructeur paramètre de type : ( nouveau : unité -> 'a ) Le type fourni doit avoir un constructeur sans paramètre.
Contrainte Type valeur type-parameter : struct Le type fourni doit être un type valeur .NET.
Contrainte Type référence type-parameter : not struct Le type fourni doit être un type de référence .NET.
Contrainte de type d’énumération type-parameter : enum<underlying-type> Le type fourni doit être un type énuméré qui a le type sous-jacent spécifié ; non destiné à une utilisation courante.
Contrainte de délégué type-parameter : delegate<tuple-parameter-type, return-type> Le type fourni doit être un type délégué qui a les arguments et la valeur de retour spécifiés ; non destiné à une utilisation courante.
Contrainte de comparaison paramètre de type : comparaison Le type fourni doit prendre en charge la comparaison.
Contrainte d’égalité type de paramètre : égalité Le type fourni doit prendre en charge l’égalité.
Contrainte non managée paramètre de type : non managé Le type fourni doit être un type non managé. Les types non managés sont soit certains types primitifs (sbyte, byte, char, nativeint, unativeint, float32, float, int16, uint16, int32, uint32, int64, uint64ou decimal), types d’énumération, nativeptr<_>, ou une structure non générique dont les champs sont tous des types non managés.

Vous devez ajouter une contrainte lorsque votre code doit utiliser une fonctionnalité disponible sur le type de contrainte, mais pas sur les types en général. Par exemple, si vous utilisez la contrainte de type pour spécifier un type de classe, vous pouvez utiliser l’une des méthodes de cette classe dans la fonction ou le type générique.

La spécification de contraintes est parfois nécessaire lors de l’écriture explicite de paramètres de type, car sans contrainte, le compilateur n’a aucun moyen de vérifier que les fonctionnalités que vous utilisez seront disponibles sur n’importe quel type qui peut être fourni au moment de l’exécution pour le paramètre de type.

Les contraintes les plus courantes que vous utilisez dans le code F# sont des contraintes de type qui spécifient des classes de base ou des interfaces. Les autres contraintes sont utilisées par la bibliothèque F# pour implémenter certaines fonctionnalités, telles que la contrainte de membre explicite, utilisée pour implémenter la surcharge d’opérateur pour les opérateurs arithmétiques, ou sont fournies principalement parce que F# prend en charge l’ensemble complet de contraintes prises en charge par le Common Language Runtime.

Pendant le processus d’inférence de type, certaines contraintes sont déduites automatiquement par le compilateur. Par exemple, si vous utilisez l’opérateur + dans une fonction, le compilateur déduit une contrainte de membre explicite sur les types de variables utilisés dans l’expression.

Le code suivant illustre certaines déclarations de contrainte :

// Base Type Constraint
type Class1<'T when 'T :> System.Exception> =
    class end

// Interface Type Constraint
type Class2<'T when 'T :> System.IComparable> =
    class end

// Null constraint
type Class3<'T when 'T : null> =
    class end

// Not Null constraint
type Class4<'T when 'T : not null> =
    class end

// Member constraint with instance member
type Class5<'T when 'T : (member Method1 : 'T -> int)> =
    class end

// Member constraint with property
type Class6<'T when 'T : (member Property1 : int)> =
    class end

// Constructor constraint
type Class7<'T when 'T : (new : unit -> 'T)>() =
    member val Field = new 'T()

// Reference type constraint
type Class8<'T when 'T : not struct> =
    class end

// Enumeration constraint with underlying value specified
type Class9<'T when 'T : enum<uint32>> =
    class end

// 'T must implement IComparable, or be an array type with comparable
// elements, or be System.IntPtr or System.UIntPtr. Also, 'T must not have
// the NoComparison attribute.
type Class10<'T when 'T : comparison> =
    class end

// 'T must support equality. This is true for any type that does not
// have the NoEquality attribute.
type Class11<'T when 'T : equality> =
    class end

type Class12<'T when 'T : delegate<obj * System.EventArgs, unit>> =
    class end

type Class13<'T when 'T : unmanaged> =
    class end

// Member constraints with two type parameters
// Most often used with static type parameters in inline functions
let inline add(value1 : ^T when ^T : (static member (+) : ^T * ^T -> ^T), value2: ^T) =
    value1 + value2

// ^T and ^U must support operator +
let inline heterogenousAdd(value1 : ^T when (^T or ^U) : (static member (+) : ^T * ^U -> ^T), value2 : ^U) =
    value1 + value2

// If there are multiple constraints, use the and keyword to separate them.
type Class14<'T,'U when 'T : equality and 'U : equality> =
    class end

Voir aussi