Ограничения (where) обобщений в C#

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

Виды ограничений

Ограничение where T : struct

Ограничивает параметр обобщения значимыми типами (структурами):

class Example<T> where T : struct
{
    public T Value { get; set; }
}

Это исключает возможность использования ссылочных типов и null.

Ограничение where T : class

Позволяет использовать только ссылочные типы:

class Example<T> where T : class
{
    public T Value { get; set; }
}

Ограничение where T : new()

Требует, чтобы тип имел открытый конструктор без параметров:

class Example<T> where T : new()
{
    public T CreateInstance() => new T();
}

Ограничение where T : BaseClass

Позволяет использовать только типы, являющиеся производными от указанного базового класса:

class Example<T> where T : BaseClass
{
}

Ограничение where T : IBaseInterface

Ограничивает параметр типами, реализующими указанный интерфейс:

class Example<T> where T : IBaseInterface
{
}

Комбинированные ограничения

Можно комбинировать несколько ограничений одновременно:

class Example<T> where T : BaseClass, IBaseInterface, new()
{
}

Ограничения для нескольких параметров

Каждый параметр может иметь свои ограничения:

class Example<T1, T2>
    where T1 : class
    where T2 : struct
{
}

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