Ograniczenia
W tym temacie opisano ograniczenia, które można zastosować do parametrów typu ogólnego, aby określić wymagania dla argumentu typu w typie ogólnym lub funkcji.
Składnia
type-parameter-list when constraint1 [ and constraint2]
Uwagi
Istnieje kilka różnych ograniczeń, które można zastosować, aby ograniczyć typy, które mogą być używane w typie ogólnym. W poniższej tabeli wymieniono i opisano te ograniczenia.
Ograniczenie | Składnia | opis |
---|---|---|
Ograniczenie typu | type-parameter :>type | Podany typ musi być równy lub pochodzić z określonego typu lub, jeśli typ jest interfejsem, podany typ musi zaimplementować interfejs. |
Ograniczenie o wartości null | type-parameter : null | Podany typ musi obsługiwać literał null. Obejmuje to wszystkie typy obiektów platformy .NET, ale nie listę F#, krotkę, funkcję, klasę, rekord lub typy unii. |
Ograniczenie jawnego elementu członkowskiego | [(]type-parameter [lub ... lub type-parameter)] : (member-signature) | Co najmniej jeden z podanych argumentów typu musi mieć element członkowski, który ma określony podpis; nie jest przeznaczony do wspólnego użytku. Elementy członkowskie muszą być jawnie zdefiniowane dla typu lub części niejawnego rozszerzenia typu, aby były prawidłowymi elementami docelowymi dla jawnego ograniczenia składowego. |
Ograniczenie konstruktora | type-parameter : ( nowa jednostka -> 'a ) | Podany typ musi mieć konstruktor bez parametrów. |
Ograniczenie typu wartości | type-parameter : struktura | Podany typ musi być typem wartości .NET. |
Ograniczenie typu odwołania | type-parameter : not, struktura | Podany typ musi być typem referencyjnym platformy .NET. |
Ograniczenie typu wyliczenia | type-parameter : wyliczenie<typu bazowego> | Podany typ musi być wyliczonym typem, który ma określony typ bazowy; nie jest przeznaczony do wspólnego użytku. |
Ograniczenie delegowania | type-parameter : delegat<tuple-parameter-type, return-type> | Podany typ musi być typem delegata, który ma określone argumenty i wartość zwracaną; nie jest przeznaczony do wspólnego użytku. |
Ograniczenie porównania | type-parameter : porównanie | Podany typ musi obsługiwać porównanie. |
Ograniczenie równości | type-parameter : równość | Podany typ musi obsługiwać równość. |
Ograniczenie niezarządzane | type-parameter : niezarządzany | Podany typ musi być typem niezarządzanym. Typy niezarządzane to niektóre typy pierwotne (sbyte , byte , nativeint float32 unativeint float uint32 int32 int16 char int64 uint64 uint16 lub decimal ), typy wyliczenia, lub struktura niegeneryczna, nativeptr<_> których pola są typami niezarządzanym. |
Należy dodać ograniczenie, gdy kod musi używać funkcji dostępnej w typie ograniczenia, ale nie w typach ogólnych. Jeśli na przykład używasz ograniczenia typu do określenia typu klasy, możesz użyć dowolnej z metod tej klasy w funkcji ogólnej lub typu.
Określenie ograniczeń jest czasami wymagane podczas jawnego pisania parametrów typu, ponieważ bez ograniczenia kompilator nie ma możliwości sprawdzenia, czy używane funkcje będą dostępne dla dowolnego typu, który może być dostarczany w czasie wykonywania dla parametru typu.
Najczęstszymi ograniczeniami używanymi w kodzie języka F# są ograniczenia typów, które określają klasy bazowe lub interfejsy. Inne ograniczenia są używane przez bibliotekę języka F# do implementowania niektórych funkcji, takich jak jawne ograniczenie składowe, które służy do implementowania przeciążenia operatora dla operatorów arytmetycznych, lub są udostępniane głównie dlatego, że język F# obsługuje pełny zestaw ograniczeń obsługiwanych przez środowisko uruchomieniowe języka wspólnego.
Podczas procesu wnioskowania typu niektóre ograniczenia są automatycznie wnioskowane przez kompilator. Jeśli na przykład używasz +
operatora w funkcji, kompilator wywnioskuje jawne ograniczenie składowe dla typów zmiennych używanych w wyrażeniu.
Poniższy kod ilustruje niektóre deklaracje ograniczeń:
// 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