Что такое обобщения (Generics) в C#

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

Зачем нужны обобщения

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

  • Повысить производительность за счет уменьшения упаковки (boxing) и распаковки (unboxing).
  • Улучшить читаемость и повторное использование кода.
  • Обеспечить безопасность типов во время компиляции.

Обобщенные классы

Обобщенные классы позволяют использовать один класс для работы с разными типами данных.

Пример обобщенного класса

using System;

class Box<T>
{
    private T value;

    public void SetValue(T value)
    {
        this.value = value;
    }

    public T GetValue()
    {
        return value;
    }
}

class Program
{
    static void Main()
    {
        Box<int> intBox = new Box<int>();
        intBox.SetValue(10);
        Console.WriteLine(intBox.GetValue());

        Box<string> stringBox = new Box<string>();
        stringBox.SetValue("Hello");
        Console.WriteLine(stringBox.GetValue());
    }
}

Обобщенные методы

Методы могут быть обобщенными, если их логика не зависит от конкретного типа данных.

Пример обобщенного метода

using System;

class Program
{
    static void Print<T>(T value)
    {
        Console.WriteLine(value);
    }

    static void Main()
    {
        Print(100);
        Print("Привет");
        Print(3.14);
    }
}

Ограничения (constraints) в обобщениях

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

Пример с ограничением

using System;

class Calculator<T> where T : struct
{
    public T Add(T a, T b)
    {
        dynamic x = a;
        dynamic y = b;
        return x + y;
    }
}

class Program
{
    static void Main()
    {
        Calculator<int> intCalc = new Calculator<int>();
        Console.WriteLine(intCalc.Add(5, 10));
    }
}

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

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

Пример обобщенного интерфейса

using System;

interface IRepository<T>
{
    void Save(T item);
}

class FileRepository : IRepository<string>
{
    public void Save(string item)
    {
        Console.WriteLine($"Сохранение в файл: {item}");
    }
}

class Program
{
    static void Main()
    {
        IRepository<string> repository = new FileRepository();
        repository.Save("Данные");
    }
}

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