Дженерики — это механизм в C#, позволяющий создавать классы, интерфейсы, структуры и методы с параметризованными типами. Это означает, что тип данных можно указать как параметр при использовании, а не при определении.
// Обобщенный (generic) класс
public class List<T> // T - параметр типа
{
public void Add(T item) { /* ... */ }
public T Get(int index) { /* ... */ }
}
// Использование с конкретным типом
List<string> stringList = new List<string>();
stringList.Add("Hello");
Без дженериков (использование object):
ArrayList list = new ArrayList();
list.Add(1); // int
list.Add("text"); // string - допустимо, но опасно
int num = (int)list[1]; // Runtime ошибка - InvalidCastException
С дженериками:
List<int> intList = new List<int>();
intList.Add(1);
intList.Add("text"); // Ошибка КОМПИЛЯЦИИ - типобезопасность
Без дженериков (упаковка/распаковка для value types):
ArrayList list = new ArrayList();
list.Add(42); // Boxing (упаковка в object)
int value = (int)list[0]; // Unboxing (распаковка)
С дженериками (нет упаковки):
List<int> list = new List<int>();
list.Add(42); // Нет boxing'а
int value = list[0]; // Нет unboxing'а
Без дженериков:
public class IntStack { public void Push(int item) { /* ... */ } }
public class StringStack { public void Push(string item) { /* ... */ } }
// Для каждого типа нужен отдельный класс!
С дженериками:
public class Stack<T>
{
public void Push(T item) { /* ... */ }
}
// Один класс для всех типов
Stack<int> intStack = new Stack<int>();
Stack<string> stringStack = new Stack<string>();
public T Max<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b) > 0 ? a : b;
}
Можно накладывать ограничения на generic-параметры:
public class Repository<T> where T : class, IEntity, new()
{
// T должен быть классом, реализовывать IEntity и иметь конструктор
}
Основные виды ограничений:
where T : struct
- value typewhere T : class
- reference typewhere T : new()
- имеет конструктор по умолчаниюwhere T : BaseClass
- наследует BaseClasswhere T : ISomeInterface
- реализует интерфейсДженерики поддерживают вариативность в интерфейсах и делегатах:
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings; // Ковариантность (out)
Action<object> actObj = o => Console.WriteLine(o);
Action<string> actStr = actObj; // Контравариантность (in)
Дженерики — мощный инструмент C#, решающий проблемы безопасности типов, производительности и дублирования кода. Они позволяют создавать гибкие, типобезопасные и эффективные обобщенные алгоритмы и структуры данных, что делает их незаменимыми в современной разработке на .NET.