Обобщённые интерфейсы
Абстрагируйтесь от конкретных типов.
«Обобщённые интерфейсы» — бесплатный урок C# Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.
Что такое обобщённый интерфейс?
Обобщённый интерфейс объявляет параметры типа в угловых скобках после своего имени. Реализующие его типы выбирают конкретные типы, и контракт интерфейса соответствующим образом адаптируется.
Библиотека .NET использует их повсюду, например IEnumerable<T> и IComparable<T>.
interface IRepository<T>
{
void Add(T item);
T Get(int id);
}Реализация обобщённого интерфейса
Класс может реализовать обобщённый интерфейс, указав конкретный аргумент типа. После этого сигнатуры методов используют этот реальный тип.
Так создаётся типобезопасный и повторно используемый контракт без приведений типов.
using System.Collections.Generic;
class IntStore : IRepository<int>
{
private readonly List<int> data = new();
public void Add(int item) => data.Add(item);
public int Get(int id) => data[id];
}
interface IRepository<T>
{
void Add(T item);
T Get(int id);
}Сохранение обобщённости в реализации
Класс может реализовать обобщённый интерфейс и при этом сам оставаться обобщённым, передавая свой параметр типа интерфейсу.
Это сохраняет возможность повторно использовать реализацию с любым типом элементов.
using System.Collections.Generic;
class Store<T> : IRepository<T>
{
private readonly List<T> data = new();
public void Add(T item) => data.Add(item);
public T Get(int id) => data[id];
}
interface IRepository<T> { void Add(T item); T Get(int id); }IComparable<T> в действии
IComparable<T> — встроенный обобщённый интерфейс. Его реализация позволяет типу определять порядок своих экземпляров и тем самым поддерживает сортировку.
Метод CompareTo возвращает отрицательное число, ноль или положительное число.
class Money : IComparable<Money>
{
public int Cents;
public int CompareTo(Money? other)
=> Cents.CompareTo(other?.Cents ?? 0);
}Реализация IEnumerable<T>
IEnumerable<T> — основа LINQ и перебора элементов. Тип, реализующий этот интерфейс, можно перебирать. Часто выполнение передают итератору внутренней коллекции.
Методы итераторов с yield return упрощают эту задачу.
using System.Collections;
using System.Collections.Generic;
class Bag<T> : IEnumerable<T>
{
private readonly List<T> items = new();
public void Add(T x) => items.Add(x);
public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}Рабочий пример обобщённого интерфейса
Эта полная программа определяет обобщённый IPrinter<T>, реализует его для строк, а затем использует его.
Интерфейс гарантирует наличие метода Print независимо от конкретного типа.
using System;
interface IPrinter<T> { void Print(T value); }
class ConsolePrinter<T> : IPrinter<T>
{
public void Print(T value) => Console.WriteLine(value);
}
class Program
{
static void Main()
{
IPrinter<string> p = new ConsolePrinter<string>();
p.Print("hello generics");
}
}Ковариантность с out
Параметр обобщённого интерфейса, отмеченный как out, является ковариантным: он используется только в позициях вывода. Поэтому IEnumerable<Cat> можно использовать там, где ожидается IEnumerable<Animal>.
Ковариантность сохраняет совместимость присваивания вдоль цепочки наследования.
interface IProducer<out T>
{
T Produce();
}Контравариантность с in
Параметр, отмеченный как in, является контравариантным: он используется только в позициях ввода. Поэтому IComparer<Animal> можно использовать там, где требуется IComparer<Cat>.
Контравариантность меняет направление допустимости присваивания для потребителей.
interface IConsumer<in T>
{
void Consume(T item);
}Несколько параметров типов
Обобщённые интерфейсы могут принимать несколько параметров. IDictionary<TKey, TValue> — знакомый пример с отдельными типами ключей и значений.
Каждый параметр независимо может быть инвариантным, ковариантным или контравариантным.
interface IMapper<TIn, TOut>
{
TOut Map(TIn input);
}Программирование через интерфейс
Зависимость от обобщённого интерфейса, а не от конкретного класса, делает код гибким. Реализации можно заменять, не изменяя вызывающий код.
Параметры методов с типом IEnumerable<T> одинаково принимают списки, массивы и результаты запросов.
using System.Collections.Generic;
using System.Linq;
int Total(IEnumerable<int> values) => values.Sum();Ограничения с использованием обобщённых интерфейсов
Обобщённые интерфейсы часто используются как ограничения. where T : IComparable<T> позволяет методу сортировать или сравнивать входные значения.
Так объединяются две возможности обобщений для создания безопасных и повторно используемых алгоритмов.
T Min<T>(T a, T b) where T : IComparable<T>
=> a.CompareTo(b) <= 0 ? a : b;Быстрая проверка
Проверьте, насколько Вы понимаете обобщённые интерфейсы.
Итоги
Обобщённые интерфейсы объявляют параметры типов и позволяют реализациям зафиксировать их или передать дальше. Встроенные примеры включают IEnumerable<T>, IComparable<T> и IDictionary<TKey, TValue>.
Аннотации вариативности out и in обеспечивают ковариантность и контравариантность, а обобщённые интерфейсы естественно сочетаются с ограничениями where.
Часто задаваемые вопросы
Урок «Обобщённые интерфейсы» бесплатный?
Да — полный текст урока «Обобщённые интерфейсы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.
Чему я научусь в уроке «Обобщённые интерфейсы»?
Абстрагируйтесь от конкретных типов. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Обобщённые интерфейсы»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Обобщённые методы
- Обобщённые классы
- Ограничения where
- Обобщённые интерфейсы