Как снижается производительность при понижающем показателе?

StackOverflow https://stackoverflow.com/questions/305755

  •  08-07-2019
  •  | 
  •  

Вопрос

Просто пытаюсь разобраться в дженериках, читая эта поучительная статья Джувала Лоуи

Перефразируя..Когда вы определяете определение универсального класса, оно компилируется в IL.

  • Для типов значений, как только вы запрашиваете определенный тип значения, он заменяет T вашим конкретным типом значения, чтобы получить IL для этой конкретной конфигурации, например MyList<int> Выгода:Никаких штрафов за боксирование и распаковку.
  • Все хорошо..для ссылочных типов компилятор заменяет все экземпляры T в вашем определении на Object и создает IL, который используется для всех типов ссылок.Экземпляры, однако, распределяются на основе фактического запрошенного типа ссылки, например MyList<String>

Теперь, до дженериков, мы могли бы написать методы, которые принимают Object параметры.Дженерики претендуют на 100% улучшение производительности, потому что 'это позволяет избежать снижения производительности, которое вы несете, когда понижаете тип объекта до вашего конкретного типа, когда хотите его использовать'

 // assume GetItem returns an Object
 string sMyPreciousString = (string) obList.GetItem(); 

Каково снижение производительности при переходе от объекта к определенному ссылочному типу?Также кажется, что приведение к объекту (даже дженерики могли бы это сделать) не влияет на производительность..почему?

Это было полезно?

Решение

Преобразование в object не требует проверки времени выполнения - оно всегда будет работать и, по сути, просто не работает.

Понижающая передача требует проверки времени выполнения, чтобы убедиться, что вы, например, не преобразуете поток в Строку.Это довольно небольшой штраф, и вряд ли он станет узким местом, но избежать его - всего лишь одно дополнительное преимущество дженериков.

Другие советы

Снижение производительности связано с необходимостью проверки типа во время выполнения.Если B является подклассом A, то когда вы приводите B в A, вы знаете во время компиляции, что это будет безопасно, поскольку все Bs являются As.Следовательно, вам не нужно генерировать какой-либо код среды выполнения для проверки типа.

Однако, когда вы преобразуете A в B, вы не знаете во время компиляции, является ли A на самом деле B или нет.Это может быть просто A, это может быть тип C, другой подтип A.Следовательно, вам нужно сгенерировать код времени выполнения, который удостоверится, что объект на самом деле является B, и выдаст исключение, если это не так.

У дженериков нет этой проблемы, потому что компилятор знает во время компиляции, что в структуру данных были введены только Bs, поэтому, когда вы извлекаете что-то, компилятор знает, что это будет B, поэтому нет необходимости в проверке типа во время выполнения.

Чтение IL, который генерируется (это Статья упоминает об этом)...ага - isinst.

Если бы вы не понижали передачу, вам бы не пришлось звонить исинст.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top