2008-11-20 3 views
4

Просто пытаясь окунуться в Generics, прочитав this enlightening article by Juval LowyКакова производительность с понижением?

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

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

В настоящее время мы предлагаем письменные методы, которые принимают параметры Object. Дженерик требуют повышений производительности 100%, потому что «это позволяет избежать потерь производительности, которые вы понесете, когда обратное приведение типа объекта к специфическому типу, когда вы хотите использовать его»

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

Что это падение производительности, когда вы опущенный от Объект для конкретного ссылочного типа? Также кажется, что up-casting для Object (даже Generics сделал бы это) не является хитом производительности .. почему?

ответ

5

Ускоренный переход на объект не требует проверки времени выполнения - он всегда будет работать и просто не работает в принципе.

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

+0

Простой, когда вы это знаете ... простой IL instr isinst для 100% -ного совершенствования :) – Gishu 2008-11-20 18:08:08

1

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

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

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

1

Чтение на ИЛ, которое генерируется (это article упоминает об этом) ... aha - isinst.

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

Смежные вопросы