Поделиться через


Ограничения

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

Синтаксис

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, float32charunativeintnativeintfloatuint32uint16int16byteint64uint64int32или 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

См. также