Ограничения where
Ограничивайте параметры типов.
«Ограничения where» — бесплатный урок C# Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.
Зачем нужны ограничения
По умолчанию параметр типа T рассматривается почти как object, поэтому компилятор разрешает для него очень мало операций. Ограничения, записываемые с помощью where, сообщают компилятору больше сведений о T.
Получив эти сведения, Вы можете безопасно вызывать методы, создавать экземпляры или сравнивать значения.
void Show<T>(T value) where T : IFormattable
{
// now ToString(format, provider) is available
}Ограничения интерфейса
Ограничение интерфейса требует, чтобы T реализовывал заданный интерфейс. После этого тело метода может вызывать члены этого интерфейса.
В примере ниже where T : IComparable<T> гарантирует наличие метода CompareTo.
T Max<T>(T a, T b) where T : IComparable<T>
=> a.CompareTo(b) >= 0 ? a : b;Ограничения базового класса
Можно потребовать, чтобы T наследовался от определённого базового класса. Тогда члены этого базового типа доступны внутри обобщённого кода.
Это часто используется в платформах, где все сущности имеют общий базовый тип.
class Animal { public string Name = ""; }
string NameOf<T>(T a) where T : Animal => a.Name;Ограничение class
where T : class требует, чтобы T был ссылочным типом. Это разрешает присваивание null и проверку равенства ссылок.
Такое ограничение типично для репозиториев, кэшей и всего, что хранит допускающие значение null ссылки.
T? FindOrNull<T>(bool found, T value) where T : class
=> found ? value : null;Ограничение struct
where T : struct требует, чтобы T был типом-значением, не допускающим значение null. Это позволяет рассматривать T как тип-значение и использовать T? как тип-значение, допускающий значение null.
Ограничение применяется во вспомогательных средствах, работающих только с числами, перечислениями или небольшими структурами.
T? AsNullable<T>(T value) where T : struct
=> value;Ограничение new()
Ограничение new() требует, чтобы у T был открытый конструктор без параметров. После этого в теле можно написать new T().
Фабрики и пулы объектов используют это ограничение для обобщённого создания экземпляров.
using System;
class Program
{
static T Make<T>() where T : new() => new T();
static void Main()
{
var list = Make<System.Collections.Generic.List<int>>();
Console.WriteLine(list.Count);
}
}Объединение ограничений
К одному параметру можно применить несколько ограничений. Правила порядка требуют сначала указать class или struct, затем базовый класс, после этого интерфейсы, а new() — в конце.
Ограничения перечисляются после одного where и разделяются запятыми.
T Build<T>() where T : class, IComparable<T>, new()
=> new T();Несколько предложений where
Если у метода или класса несколько параметров типа, для каждого используется собственное предложение where. Они записываются одно за другим.
Так ограничения каждого параметра остаются чётко отделёнными друг от друга.
TResult Convert<TInput, TResult>(TInput x)
where TInput : class
where TResult : new()
=> new TResult();Рабочий пример обобщённого ограничения
Эта полная программа использует ограничение IComparable<T>, чтобы найти большее из двух значений, работая и с целыми числами, и со строками.
Именно ограничение делает вызов CompareTo допустимым внутри метода.
using System;
class Program
{
static T Max<T>(T a, T b) where T : IComparable<T>
=> a.CompareTo(b) >= 0 ? a : b;
static void Main()
{
Console.WriteLine(Max(3, 9));
Console.WriteLine(Max("apple", "pear"));
}
}Ограничения notnull и unmanaged
В новых версиях C# появились дополнительные ограничения. where T : notnull запрещает типы, допускающие значение null, что полезно для ключей словаря. where T : unmanaged ограничивает T типами-значениями, совместимыми с простым представлением в памяти, для низкоуровневого кода.
Эти ограничения повышают безопасность в специализированных сценариях.
void Use<T>(T key) where T : notnull { }
unsafe void Raw<T>(T v) where T : unmanaged { }Ограничения открывают возможности, а не ограничивают их
Хотя ограничения выглядят как запреты, на самом деле они открывают дополнительные возможности. Без ограничения с T почти ничего нельзя сделать, а с ним становятся доступны его члены.
Выбирайте минимальное ограничение, достаточное для работы алгоритма, чтобы параметр типа оставался как можно более гибким.
// No constraint: only object members available
string Name<T>(T x) => x.ToString();Быстрая проверка
Проверьте, насколько Вы понимаете ограничения where.
Повторение
Предложение where ограничивает параметры типа: интерфейсом, базовым классом, class, struct, new(), notnull или unmanaged. Каждое ограничение открывает определённые операции над T.
Соблюдайте правильный порядок, используйте одно предложение для каждого параметра и выбирайте минимальное ограничение, необходимое алгоритму.
Часто задаваемые вопросы
Урок «Ограничения where» бесплатный?
Да — полный текст урока «Ограничения where» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.
Чему я научусь в уроке «Ограничения where»?
Ограничивайте параметры типов. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Ограничения where»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Обобщённые методы
- Обобщённые классы
- Ограничения where
- Обобщённые интерфейсы