Дженерики (обобщенные типы) - это механизм, позволяющий создавать классы, интерфейсы и методы с заполнителями для типов, которые заменяются конкретными типами во время компиляции или выполнения.
public class List<T> // T - параметр типа
{
public void Add(T item) { ... }
public T Get(int index) { ... }
}
// Использование
var intList = new List<int>(); // int - аргумент типа
В отличие от шаблонов C++, .NET дженерики:
// В runtime будут созданы разные специализации:
List<int> // Отдельный тип
List<string> // Отдельный тип
List<object> // Отдельный тип
Для ссылочных типов используется общая реализация (из-за одинакового размера указателей):
// Эти специализации используют одну реализацию в runtime:
List<string>
List<Stream>
List<MyClass>
При компиляции в IL сохраняется информация:
.class public auto ansi beforefieldinit List`1<T>
{
.method public hidebysig instance void Add(!T item) cil managed
}
При первом использовании:
public T Max<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b) > 0 ? a : b;
}
Основные виды ограничений:
where T : struct
- значимый типwhere T : class
- ссылочный типwhere T : new()
- имеет конструктор по умолчаниюwhere T : BaseClass
- наследование от классаwhere T : ISomeInterface
- реализация интерфейсаIEnumerable<out T> // T только в выходных позициях
IEnumerable<string> strings = ...;
IEnumerable<object> objects = strings; // Безопасно
IComparer<in T> // T только во входных позициях
IComparer<object> objComparer = ...;
IComparer<string> strComparer = objComparer; // Безопасно
Отражение (Reflection):
typeof(T)
Type.GetGenericArguments()
для анализаСтатические поля:
class Counter<T>
{
public static int Count;
}
Counter<int>.Count++; // Не влияет на Counter<string>.Count
дженерики в .NET реализованы на уровне CLR с поддержкой runtime-специализации, что обеспечивает безопасность типов и производительность без дублирования кода. Механизм включает сложную систему ограничений, вариантности и интеграцию с системой типов .NET.