Почему специализация в С# generics ограничена?

Вопрос "Что такое reification?" имеет комментарий к обобщающим файлам С#:

Поддерживается информация о типе, которая позволяет специализация, изучая аргументы типа с использованием отражения. Однако степень специализации ограничена в результате того, что определение общего типа компилируется до того, как произойдет какое-либо повторное подтверждение (это делается путем компиляции определения с ограничениями на параметры типа - таким образом, компилятор должен уметь "понимать" определение даже при отсутствии конкретных аргументов типа).

  • Что означает "специализация"? Это не то же самое, что и создание экземпляра типичного типа с определенным аргументом типа?

  • Что означает "степень специализации ограничена"?

  • Почему это "результат того, что определение общего типа компилируется до того, как произойдет какое-либо повторное подтверждение"?

Ответ 1

Что означает "специализация"? Это не то же самое, что создание экземпляра типичного типа с определенным аргументом типа?

Автор объясняет в части своего ответа, посвященной Java-дженерикам, которые

специализация универсального типа [является] способностью использовать специализированный исходный код для любой конкретной общей комбинации аргументов.

Другими словами, это способность делать что-то особенное, если общий тип типа имеет определенный тип. Поставка реализации List<T>, которая представляет отдельные элементы в виде битов, когда вы создаете экземпляр типа List<bool>, будет примером специализации.

Что означает "степень специализации ограничена"?

Автор означает, что, хотя вы можете писать такие вещи, как

if (typeof(T) == typeof(bool)) {
    ...
}

ваши способности реагировать на комбинацию аргументов типа ограничены, так как любое решение о комбинации типов должно выполняться во время выполнения.

Почему это "результат того факта, что определение общего типа компилируется до того, как произойдет какое-либо повторение"?

Потому что reification сделано в CLR, ну после компилятора С# вне изображения. Компилятор должен создать общее определение типа для CLR для использования в качестве "шаблона" для создания замкнутых построенных типов для экземпляров родового класса.

Ответ 2

Я считаю, что смысл таков:

Когда вы определяете общий тип, например. MyGenericType<T> ваше определение должно иметь смысл для любого значения T, поскольку общий тип скомпилирован до того, как вы действительно используете его в конкретной реализации ( "степень специализации ограничена в результате того, что определение общего типа скомпилирован до того, как произойдет какое-либо повторное подтверждение" ).

Позже, когда вы на самом деле используете MyGenericType<int>, компилятор /jit создаст новый класс, который в значительной степени MyGenericType<T>, при каждом упоминании T заменяется на int. Это процесс овеществления. Это означает, что во время выполнения вы можете использовать тот факт, что общий тип использует int, но ваша способность использовать эту (специализацию) ограничена, поскольку, когда вы определили MyGenericType<T>, вы этого не знали.

Ответ 3

Специализация используется как антоним для обобщения. Когда вы создали общий тип, вы обобщили определение типа. Когда вы инициализировали его типом, вы специализировали скомпилированный общий тип, чтобы иметь возможность создавать объект типа во время выполнения.

IL компилирует общий тип. Во время выполнения этот скомпилированный общий тип объединяется с определенным аргументом типа для создания объекта указанного класса.

Да, специализация такая же, как и создание типичного типа с определенным аргументом типа во время выполнения.

С generics возникают ограничения, которые в основном фиксируют область родового типа. Вы можете сказать, что, определяя, что T может быть структурой, классом или должен иметь некоторый определенный базовый класс и т.д. Вы не можете создать экземпляр класса, который не допускается ограничениями, определенными в родовом типе.

Вы можете инициализировать то же определение общего типа с помощью int, string или другого класса, если оно удовлетворяет ограничениям в классе generic. Он не может напрямую создать объект класса с T, который еще не заменен определенным типом (примитивные типы, такие как int, string или ваш собственный класс или интерфейс), а ваш код внутри должен быть совместим с типом, передаваемым как T для него работать.

Обратитесь (ссылки из того же вопроса, о котором вы говорили выше):

NET Generics и Code Bloat

Генерики не являются шаблонами (как на С++)