限制
本主題描述可以套用至泛型型別參數的條件約束,以指定泛型型別或函式中型別引數的需求。
語法
type-parameter-list when constraint1 [ and constraint2]
備註
您可以套用數種不同的條件約束來限制可用於泛型型別的型別。 下表列出並描述這些條件約束。
條件約束 | 語法 | 描述 |
---|---|---|
型別條件約束 | type-parameter :>type | 所提供的型別必須等於或衍生自指定的型別,或者,如果型別是介面,則所提供的型別必須實作介面。 |
null 條件約束 | type-parameter : null | 所提供的型別必須支援 null 常值。 這包括所有 .NET 物件型別,但不包含 F# 清單、元組、函式、類別、記錄或等位型別。 |
明確成員條件約束 | [(]type-parameter [or ... or type-parameter)] : (member-signature) | 所提供的型別引數中,至少必須有一個具有指定特徵標記的成員;不適用於一般用途。 成員必須明確定義於型別,或定義為隱含類型延伸的一部分,才能成為明確成員條件約束的有效目標。 |
建構函式條件約束 | type-parameter : ( new : unit -> 'a ) | 所提供的型別必須有無參數建構函式。 |
實值型別條件約束 | type-parameter : struct | 所提供的型別必須是 .NET 實值型別。 |
參考型別條件約束 | type-parameter : not struct | 所提供的型別必須是 .NET 參考型別。 |
列舉型別條件約束 | type-parameter : enum<underlying-type> | 所提供的型別必須是具有指定基礎型別的列舉型別;不適用於一般用途。 |
委派條件約束 | type-parameter : delegate<tuple-parameter-type, return-type> | 所提供的型別必須是具有指定引數和傳回值的委派型別;不適用於一般用途。 |
比較條件約束 | type-parameter : comparison | 所提供的型別必須支援比較。 |
相等條件約束 | type-parameter : equality | 所提供的型別必須支援相等。 |
非受控條件約束 | type-parameter : unmanaged | 所提供的型別必須是非受控型別。 非受控型別可以是某些基本型別 (sbyte 、byte 、char 、nativeint 、unativeint 、float32 、float 、int16 、uint16 、int32 、uint32 、int64 、uint64 或 decimal )、列舉型別、nativeptr<_> 或欄位為非受控型別的非泛型結構。 |
當程式碼必須使用條件約束型別上可用的功能,而非一般型別上可用的功能時,您必須新增條件約束。 例如,如果您使用型別條件約束來指定類別型別,則可以在泛型函式或型別中使用該類別的任何一個方法。
在明確寫入型別參數時,有時需要指定條件約束,因為如果沒有條件約束,編譯器就無法驗證您使用的功能是否可在型別參數的執行階段可能提供的任何類型上使用。
您在 F# 程式碼中使用的最常見條件約束是用來指定基底型別或介面的型別條件約束。 F# 程式庫會使用其他條件約束來實作某些功能 (例如明確成員條件約束,用來實作算術運算子的運算子多載),或者,提供其他條件約束的主要原因是 F# 支援 Common Language Runtime 所支援的完整條件約束集。
在型別推斷程序進行期間,編譯器會自動推斷某些條件約束。 例如,如果您在函式中使用 +
運算子,則編譯器會在運算式中使用的變數型別上推斷明確的成員條件約束。
下列程式碼會說明一些條件約束宣告:
// 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