約束
本主題描述您可以套用至泛型類型參數的條件約束,以指定泛型類型或函式中類型自變數的需求。
語法
type-parameter-list when constraint1 [ and constraint2]
備註
您可以套用數個不同的條件約束來限制可用於泛型型別的類型。 下表列出並描述這些條件約束。
限制 | 語法 | 描述 |
---|---|---|
類型限制 | 類型參數:>類型 | 提供的型別必須等於或衍生自指定的型別,或者,如果型別是介面,則提供的型別必須實作 介面。 |
空值約束 | type-parameter:null | 提供的型別必須支援 Null 值。 這包括所有 .NET 物件類型,但不包括 F# 清單、Tuple、函式、類別、記錄或等位類型。 |
非空約束 | 型參數 : 不可為空 | 提供的型別不得支援 Null 值。 不允許 null 批注型別,以及其具有 null 作為表示值的型別(例如選項型別或使用 AllowNullLiteral 屬性定義的類型)。 此泛型條件約束確實允許實值型別,因為這些類型永遠不能是 Null。 |
明確成員限制條件 | [(]類型參數 [或 ...或 類型參數)] : (成員簽名) | 至少提供的一個型別參數必須有具有指定簽章的成員;不適合一般用途。 成員必須明確定義於類型或隱式類型擴展的一部分,才能成為顯式成員約束條件的有效目標。 |
建構函式條件約束 | 型別參數:(新建:單位 -> 'a') | 提供的型別必須具有無參數建構函式。 |
值類型限制 | type-parameter:結構體 | 提供的型別必須是 .NET 實值型別。 |
參考類型約束 | 型別參數:非結構 | 提供的型別必須是 .NET 參考型別。 |
列舉型別條件約束 | type-parameter:列舉型別<底層類型> | 提供的型別必須是具有指定基礎型別的列舉型別;不適用於一般用途。 |
委派限制 | type-parameter:委派<tuple-parameter-type,return-type> | 提供的型別必須是具有指定自變數和傳回值的委派型別;不適用於一般用途。 |
比較約束條件 | 類型參數:比較 | 提供的型別必須支持比較。 |
相等條件約束 | 型別參數:相等性 | 提供的型別必須支援相等。 |
未管理的限制 | 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
// 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