where (ограничение универсального типа) (справочник по C#)where (generic type constraint) (C# Reference)

Предложение where в универсальном определении задает ограничения на типы, которые используются в качестве аргументов для параметров типа в универсальном типе, методе, делегате или локальной функции.The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Ограничения могут задавать интерфейсы, базовые классы или требовать, чтобы универсальный тип был ссылочным типом, типом значения или неуправляемым типом.Constraints can specify interfaces, base classes, or require a generic type to be a reference, value or unmanaged type. Они объявляют характеристики, которыми должен обладать аргумент типа.They declare capabilities that the type argument must possess.

Например, можно объявить универсальный класс MyGenericClass так, чтобы параметр типа T реализовывал интерфейс IComparable<T>:For example, you can declare a generic class, MyGenericClass, such that the type parameter T implements the IComparable<T> interface:

public class AGenericClass<T> where T : IComparable<T> { }

Примечание

Дополнительные сведения о предложении where в выражении запроса см. в разделе Предложение where.For more information on the where clause in a query expression, see where clause.

Предложение where также может включать ограничение базового класса.The where clause can also include a base class constraint. Ограничение базового класса указывает, что тип, который должен использоваться как аргумент типа для этого универсального типа, имеет заданный класс в качестве базового класса (или является этим базовым классом), который должен использоваться как аргумент типа для этого универсального типа.The base class constraint states that a type to be used as a type argument for that generic type has the specified class as a base class (or is that base class) to be used as a type argument for that generic type. Если ограничение базового класса используется, оно должно быть указано перед любыми другими ограничениями данного параметра типа.If the base class constraint is used, it must appear before any other constraints on that type parameter. Некоторые типы не могут использоваться как ограничение базового класса: Object, Array и ValueType.Some types are disallowed as a base class constraint: Object, Array, and ValueType. До C# 7.3 Enum, Delegate и MulticastDelegate также не могли использоваться в качестве ограничений базового класса.Prior to C# 7.3, Enum, Delegate, and MulticastDelegate were also disallowed as base class constraints. Ниже приведен пример типов, которые теперь можно указать как базовый класс:The following example shows the types that can now be specified as a base class:

public class UsingEnum<T> where T : System.Enum { }

public class UsingDelegate<T> where T : System.Delegate { }

public class Multicaster<T> where T : System.MulticastDelegate { }

Предложение where может указывать, что тип является class или struct.The where clause can specify that the type is a class or a struct. Ограничение struct избавляет от необходимости указывать ограничение базового класса System.ValueType.The struct constraint removes the need to specify a base class constraint of System.ValueType. Тип System.ValueType не может использоваться как ограничение базового класса.The System.ValueType type may not be used as a base class constraint. Ограничения class и struct показаны в следующем примере:The following example shows both the class and struct constraints:

class MyClass<T, U>
    where T : class
    where U : struct
{ }

Предложение where также может включать ограничение unmanaged.The where clause may also include an unmanaged constraint. Ограничение unmanaged позволяет использовать в качестве параметра типа только типы, называемые неуправляемыми типами.The unmanaged constraint limits the type parameter to types known as unmanaged types. Неуправляемый тип — это тип, который не является ссылочным и не содержит поля ссылочного типа на любом уровне вложения.An unmanaged type is a type that isn't a reference type and doesn't contain reference type fields at any level of nesting. Ограничение unmanaged упрощает написание кода взаимодействия низкого уровня на языке C#.The unmanaged constraint makes it easier to write low-level interop code in C#. Это ограничение включает подпрограммы с возможностью повторного использования для всех неуправляемых типов.This constraint enables reusable routines across all unmanaged types. Ограничение unmanaged нельзя использовать с ограничением class или struct.The unmanaged constraint can't be combined with the class or struct constraint. Ограничение unmanaged требует тип struct:The unmanaged constraint enforces that the type must be a struct:

class UnManagedWrapper<T>
    where T : unmanaged
{ }

Предложение where также может включать ограничение конструктора, new().The where clause may also include a constructor constraint, new(). Это ограничение позволяет создать экземпляр параметра типа с помощью оператора new.That constraint makes it possible to create an instance of a type parameter using the new operator. Ограничение new() сообщает компилятору о том, что все предоставленные аргументы типа должны иметь доступный конструктор без параметров (или конструктор по умолчанию).The new() Constraint lets the compiler know that any type argument supplied must have an accessible parameterless--or default-- constructor. Пример:For example:

public class MyGenericClass<T> where T : IComparable<T>, new()
{
    // The following line is not possible without new() constraint:
    T item = new T();
}

Ограничение new() отображается в предложении where последним.The new() constraint appears last in the where clause. Ограничение new() не может использоваться с ограничениями struct или unmanaged.The new() constraint can't be combined with the struct or unmanaged constraints. Все типы, удовлетворяющие этим ограничениям, должны иметь доступ к конструктору без параметров, поэтому ограничение new() будет избыточным.All types satisfying those constraints must have an accessible parameterless constructor, making the new() constraint redundant.

Если параметров типа несколько, для каждого из них необходимо использовать по одному предложению where, например:With multiple type parameters, use one where clause for each type parameter, for example:

public interface IMyInterface { }

namespace CodeExample
{
    class Dictionary<TKey, TVal>
        where TKey : IComparable<TKey>
        where TVal : IMyInterface
    {
        public void Add(TKey key, TVal val) { }
    }
}

Кроме того, ограничения можно присоединять к параметрам типа универсальных методов следующим образом:You can also attach constraints to type parameters of generic methods, as shown in the following example:

public void MyMethod<T>(T t) where T : IMyInterface { }

Обратите внимание на то, что ограничения параметров типа для делегатов имеют такой же синтаксис, как и методы:Notice that the syntax to describe type parameter constraints on delegates is the same as that of methods:

delegate T MyDelegate<T>() where T : new();

Дополнительные сведения об универсальных делегатах см. в разделе Универсальные делегаты.For information on generic delegates, see Generic Delegates.

Дополнительные сведения о синтаксисе и применении ограничений см. в разделе Ограничения параметров типа.For details on the syntax and use of constraints, see Constraints on Type Parameters.

Спецификация языка C#C# language specification

Дополнительные сведения см. в спецификации языка C#.For more information, see the C# Language Specification. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.The language specification is the definitive source for C# syntax and usage.

См. такжеSee also