Вопрос о моменте создания специализированных дженерик-типов в C# вызывает много дискуссий. Давайте разберемся детально:
Во время компиляции:
Во время выполнения (JIT-компиляция):
List<int>
, List<string>
и т.д.)// Обобщенный класс (не создается в бинарнике как готовый код)
public class GenericBox<T> {
public T Value { get; set; }
}
// При первом использовании в runtime:
var intBox = new GenericBox<int>(); // JIT генерирует специализированный код для int
var stringBox = new GenericBox<string>(); // Затем для string
Кэширование типов:
Разделение кода:
List<string>
, List<object>
) используется один экземпляр кодаList<int>
, List<DateTime>
) создаются отдельные реализацииДинамическая генерация:
System.Reflection.Emit
можно создавать дженерик-типы полностью во время выполненияTiered JIT-компиляция:
Generic Sharing:
Размер исполняемого файла:
Производительность:
// Измерение времени первой генерации
var watch = System.Diagnostics.Stopwatch.StartNew();
var list = new List<MyCustomType>(); // Включает генерацию кода
watch.Stop();
Console.WriteLine($"First gen time: {watch.ElapsedTicks} ticks");
дженерик-классы конкретных типов генерируются во время выполнения при первом использовании каждой уникальной комбинации параметров типа, а не во время компиляции. Это ключевая особенность реализации дженериков в .NET, обеспечивающая баланс между гибкостью и производительностью.