Ограничения
В этом разделе описываются ограничения, которые можно применить к параметрам универсального типа, чтобы указать требования к аргументу типа в универсальном типе или функции.
Синтаксис
type-parameter-list when constraint1 [ and constraint2]
Замечания
Существует несколько различных ограничений, которые можно применить, чтобы ограничить типы, которые можно использовать в универсальном типе. В следующей таблице перечислены и описываются эти ограничения.
Ограничение | Синтаксис | Description |
---|---|---|
Ограничение типа | type-parameter :>type | Указанный тип должен быть равным или производным от указанного типа или, если тип является интерфейсом, указанный тип должен реализовать интерфейс. |
Ограничение NULL | type-parameter : null | Предоставленный тип должен поддерживать литерал NULL. Сюда входят все типы объектов .NET, но не список F#, кортеж, функция, класс, запись или типы объединения. |
Явное ограничение члена | [(]type-parameter [или ... или type-parameter)] : (сигнатура участника) | По крайней мере один из указанных аргументов типа должен иметь член, имеющий указанную подпись; не предназначено для общего использования. Элементы должны быть явно определены в типе или части неявного расширения типа, чтобы быть допустимыми целевыми объектами для явного ограничения члена. |
Ограничение конструктора | type-parameter : ( new : unit -> a ) | Указанный тип должен иметь конструктор без параметров. |
Ограничение типа значения | type-parameter : struct | Указанный тип должен быть типом значения .NET. |
Ограничение ссылочного типа | type-parameter : не структуру | Указанный тип должен быть ссылочным типом .NET. |
Ограничение типа перечисления | type-parameter : перечисление<базового типа> | Указанный тип должен быть перечисленным типом, который имеет указанный базовый тип; не предназначено для общего использования. |
Ограничение делегата | type-parameter: делегат<кортежа-parameter-type, return-type> | Указанный тип должен быть типом делегата, который имеет указанные аргументы и возвращаемое значение; не предназначено для общего использования. |
Ограничение сравнения | тип-параметр : сравнение | Указанный тип должен поддерживать сравнение. |
Ограничение равенства | type-parameter : равенство | Предоставленный тип должен поддерживать равенство. |
Неуправляемые ограничения | type-parameter : неуправляемый | Указанный тип должен быть неуправляемым типом. Неуправляемые типы — это определенные примитивные типы (sbyte , float32 char unativeint nativeint float uint32 uint16 int16 byte int64 uint64 int32 или decimal ), типы nativeptr<_> перечисления, или не универсальная структура, поля которых являются всеми неуправляемыми типами. |
Необходимо добавить ограничение, если код должен использовать функцию, доступную по типу ограничения, но не к типам в целом. Например, если вы используете ограничение типа для указания типа класса, можно использовать любой из методов этого класса в универсальной функции или типе.
Указание ограничений иногда требуется при явном написании параметров типа, так как без ограничения компилятор не имеет способа проверить, будут ли используемые функции доступны в любом типе, который может быть предоставлен во время выполнения для параметра типа.
Наиболее распространенные ограничения, используемые в коде F#, — это ограничения типов, которые указывают базовые классы или интерфейсы. Другие ограничения используются библиотекой F# для реализации определенных функций, таких как явное ограничение члена, которое используется для реализации перегрузки операторов для арифметических операторов или предоставляется главным образом потому, что F# поддерживает полный набор ограничений, поддерживаемых средой CLR.
Во время процесса вывода типов некоторые ограничения автоматически выводятся компилятором. Например, если оператор используется +
в функции, компилятор вводит явное ограничение члена для типов переменных, используемых в выражении.
В следующем коде показаны некоторые объявления ограничений:
// 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