Ограничения

В этом разделе описываются ограничения, которые можно применять к параметрам универсального типа для указания требований для аргумента типа в универсальном типе или функции.

Синтаксис

type-parameter-list when constraint1 [ and constraint2]

Remarks

Существует несколько различных ограничений, которые можно применить для ограничения типов, которые могут использоваться в универсальном типе. В следующей таблице перечислены и описаны эти ограничения.

Ограничение Синтаксис Описание
Ограничение типа тип-параметр : тип Указанный тип должен быть равен или производному от указанного типа, или, если тип является интерфейсом, предоставленный тип должен реализовывать интерфейс.
Ограничение null тип-параметр : NULL Указанный тип должен поддерживать литерал null. Сюда входят все типы объектов .NET, но не типы списка, кортежа, функции, класса, записи или объединения F #.
Ограничение явного члена [(]тип-параметр [или... или Type-Parameter)]: (подпись члена) По крайней мере один из указанных аргументов типа должен иметь член с указанной сигнатурой. не предназначено для общего использования. Члены должны быть либо явно определены в типе, либо частью расширения неявного типа, чтобы быть допустимыми целевыми объектами для ограничения явного члена.
Ограничение конструктора Type — параметр : (New: Unit- "a) Указанный тип должен иметь конструктор без параметров.
Ограничение типа значения : структура Указанный тип должен быть типом значения .NET.
Ограничение ссылочного типа : не структура Указанный тип должен быть ссылочным типом .NET.
Ограничение типа перечисления :< перечисления <> Указанный тип должен быть перечислимым типом с указанным базовым типом. не предназначено для общего использования.
Ограничение делегата : кортеж делегата <<, возвращаемый тип Указанный тип должен быть типом делегата с указанными аргументами и возвращаемым значением. не предназначено для общего использования.
Ограничение сравнения : сравнение Указанный тип должен поддерживать сравнение.
Ограничение на равенство : равенство Указанный тип должен поддерживать равенство.
Неуправляемое ограничение : неуправляемый Указанный тип должен иметь неуправляемый тип. Неуправляемые типы являются определенными примитивными типами ( sbyte , byte , char , unativeintnativeintfloat32 ,,, float , uint16int16 ,, uint32int32uint64int64 ,,, или 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

См. также раздел