Begränsningar
Det här avsnittet beskriver begränsningar som du kan använda för generiska typparametrar för att ange kraven för ett typargument i en allmän typ eller funktion.
Syntax
type-parameter-list when constraint1 [ and constraint2]
Kommentarer
Det finns flera olika begränsningar som du kan använda för att begränsa vilka typer som kan användas i en allmän typ. I följande tabell visas och beskrivs dessa begränsningar.
Begränsning | Syntax | beskrivning |
---|---|---|
Typvillkor | type-parameter :>type | Den angivna typen måste vara lika med eller härledd från den angivna typen, eller, om typen är ett gränssnitt, måste den angivna typen implementera gränssnittet. |
Null-villkor | type-parameter : null | Den angivna typen måste ha stöd för null-literalen. Detta omfattar alla .NET-objekttyper men inte F#-lista, tuppeln, funktionen, klassen, posten eller unionstyperna. |
Explicit medlemsbegränsning | [(]type-parameter [eller ... eller type-parameter)] : (member-signature) | Minst ett av de angivna typargumenten måste ha en medlem som har den angivna signaturen. är inte avsedd för vanlig användning. Medlemmar måste antingen uttryckligen definieras för typen eller en del av ett implicit typtillägg för att vara giltiga mål för en explicit medlemsbegränsning. |
Konstruktorvillkor | type-parameter : ( new : unit -> 'a ) | Den angivna typen måste ha en parameterlös konstruktor. |
Villkor för värdetyp | type-parameter : struct | Den angivna typen måste vara en .NET-värdetyp. |
Villkor för referenstyp | type-parameter : not struct | Den angivna typen måste vara en .NET-referenstyp. |
Villkor för uppräkningstyp | type-parameter : räkna upp<underliggande typ> | Den angivna typen måste vara en uppräknad typ som har den angivna underliggande typen. är inte avsedd för vanlig användning. |
Villkor för ombud | type-parameter : delegate<tuple-parameter-type, return-type> | Den angivna typen måste vara en ombudstyp som har de angivna argumenten och returvärdet. är inte avsedd för vanlig användning. |
Jämförelsevillkor | type-parameter : jämförelse | Den angivna typen måste ha stöd för jämförelse. |
Likhetsbegränsning | type-parameter : equality | Den angivna typen måste ha stöd för likhet. |
Ohanterad begränsning | type-parameter : ohanterad | Den angivna typen måste vara en ohanterad typ. Ohanterade typer är antingen vissa primitiva typer (sbyte , , byte char , nativeint , unativeint , float32 , float , int16 , uint16 , int32 , uint32 , , int64 , uint64 eller decimal ), uppräkningstyper, nativeptr<_> eller en icke-generisk struktur vars fält alla är ohanterade typer. |
Du måste lägga till en begränsning när koden måste använda en funktion som är tillgänglig för villkorstypen men inte på typer i allmänhet. Om du till exempel använder typvillkoret för att ange en klasstyp kan du använda någon av metoderna för den klassen i den generiska funktionen eller typen.
Att ange begränsningar krävs ibland när du uttryckligen skriver typparametrar, eftersom kompilatorn inte har något sätt att verifiera att de funktioner som du använder är tillgängliga för alla typer som kan anges vid körning för typparametern.
De vanligaste begränsningarna som du använder i F#-kod är typbegränsningar som anger basklasser eller gränssnitt. De andra begränsningarna används antingen av F#-biblioteket för att implementera vissa funktioner, till exempel den explicita medlemsbegränsningen, som används för att implementera operatoröverlagring för aritmetiska operatorer, eller tillhandahålls främst eftersom F# stöder den fullständiga uppsättningen begränsningar som stöds av den gemensamma språkkörningen.
Under typinferensprocessen härleds vissa begränsningar automatiskt av kompilatorn. Om du till exempel använder operatorn +
i en funktion härleder kompilatorn en explicit medlemsbegränsning för variabeltyper som används i uttrycket.
Följande kod illustrerar vissa villkorsdeklarationer:
// 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
// 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