0Pricing
C# Academy · Урок

Обобщённые интерфейсы

Абстрагируйтесь от конкретных типов.

«Обобщённые интерфейсы» — бесплатный урок 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 — локальная установка не требуется.

Все уроки этого курса

  1. Обобщённые методы
  2. Обобщённые классы
  3. Ограничения where
  4. Обобщённые интерфейсы
← Назад к C# Academy