Как ответить
Дженерики — это механизм параметризации типов, который позволяет писать код, работающий с разными типами данных без потери типобезопасности на этапе компиляции. В Java, C# и TypeScript они решают одну и ту же проблему: избавляют от ручных приведений типов и предотвращают ClassCastException в рантайме. Разница в реализации: Java использует стирание типов (erasure), C# — конкретизацию (reification), а TypeScript — чисто статическую проверку без влияния на рантайм.
Рассмотрим на примере Java. Класс Box<T>:
public class Box<T> {
private T value;
public void set(T value) { this.value = value; }
public T get() { return value; }
}Тип T — это параметр. При использовании Box<String> компилятор:
- Проверяет, что в
set()передаётся толькоString; - Вставляет неявное приведение к
Stringпри вызовеget(); - После проверки стирает информацию о типе: в байт-коде поле
valueстановитсяObject, а методы получают брейджинг с кастами.
Из-за стирания в Java есть ограничения: нельзя создать экземпляр new T(), массив new T[10] (но можно через (T[]) new Object[10] — с предупреждением), или использовать instanceof с параметром типа. Wildcards (? extends T, ? super T) добавляют гибкости, но подчиняются тем же правилам стирания.
В C# дженерики работают иначе: для reference-типов генерируется один код с объектными ссылками, а для value-типов — отдельная специализация (например, List<int> и List<double> — разный машинный код). Это позволяет хранить примитивы без упаковки (boxing) и сохранять точную информацию о типе в рантайме. В C# можно создавать экземпляры через new T() при наличии ограничения where T : new().
В TypeScript дженерики существуют только в исходном коде — после компиляции в JS от них не остаётся и следа. Это удобно для библиотек вроде Array<T> или Promise<T>, но требует осторожности: в рантайме тип может не совпадать с объявленным.
На практике дженерики — незаменимый инструмент для создания коллекций, алгоритмов и абстракций, где тип данных не фиксирован. Для middle-разработчика важно понимать не только синтаксис, но и внутреннюю механику: стирание типов влияет на перегрузку, рефлексию и производительность, а специализация C# — на размер кода и скорость.