條件約束 (F#)
本主題描述可套用至泛型型別參數的條件約束,以指定泛型型別或函式中型別引數的需求。
type-parameter-list when constraint1 [ and constraint2]
備註
您可以套用多個不同的條件約束,以限制泛型型別中的可用型別。下表列出並描述這些條件約束。
條件約束 |
語法 |
描述 |
---|---|---|
型別條件約束 |
type-parameter :> type |
提供的型別必須等於或衍生自指定的型別,如果型別為介面,則提供的型別必須實作此介面。 |
Null 條件約束 |
type-parameter : null |
提供的型別必須支援 null 常值,這包含所有 .NET 物件型別,但不包含 F# 清單、Tuple、函式、類別、記錄或聯集型別。 |
明確成員條件約束 |
[(]type-parameter [或…或 type-parameter]):(member-signature) |
至少其中一個提供的型別引數必須有指定之簽章的成員,因此不適用於一般用途。 |
建構函式條件約束 |
type-parameter : ( new : unit -> 'a ) |
提供的型別必須有預設的建構函式。 |
實值型別條件約束 |
: struct |
提供的型別必須是 .NET 實值型別。 |
參考型別條件約束 |
: not struct |
提供的型別必須是 .NET 參考型別。 |
列舉型別條件約束 |
: enum<underlying-type> |
提供的型別必須是有指定之基礎型別的列舉型別,因此不適用於一般用途。 |
委派條件約束 |
: delegate<tuple-parameter-type, return-type> |
提供的型別必須是有指定之引數和傳回值的委派型別,因此不適用於一般用途。 |
比較條件約束 |
: comparison |
提供的型別必須支援比較。 |
相等條件約束 |
: equality |
提供的型別必須支援相等。 |
Unmanaged 條件約束 |
: unmanaged |
提供的型別必須是 Unmanaged 型別。Unmanaged 型別是特定基本型別 (sbyte、byte、char、nativeint、unativeint、float32、float、int16、uint16、int32、uint32、int64、uint64 或 decimal)、列舉型別、nativeptr<_> 或其欄位是所有 Unmanaged 型別的非泛型結構。 |
當程式碼必須使用的功能適用於條件約束型別但不適用於一般型別時,您必須加入條件約束。例如,如果您使用型別條件約束來指定類別型別,就可以在泛型函式或型別中,使用該類別的任何一個方法。
明確撰寫型別參數時有時需要指定條件約束,因為如果沒有條件約束,編譯器便無法驗證所使用的功能是否可用於執行階段提供給型別參數的任何型別。
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 static member
type Class4<'T when 'T : (static member staticMethod1 : unit -> 'T) > =
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