Когда оператор использования упаковывает свой аргумент, когда это - структура?

Синтаксическая краткая сахарная вещь - Кэширует объектный набор и выполняет команды на одной строке:

Вместо:

var jQueryCollection = $("");

jQueryCollection.command().command();

я делаю:

var jQueryCollection = $("").command().command();

А несколько "реальный" вариант использования мог быть чем-то вдоль этих строк:

var cache = $("#container div.usehovereffect").mouseover(function ()
{
    cache.removeClass("hover").filter(this).addClass("hover");
});
6
задан Lasse V. Karlsen 25 August 2009 в 19:55
поделиться

3 ответа

Похоже, что любой тип значения, помещенный в с использованием оператора , не будет упакован. Похоже, это оптимизация C #, поскольку упаковка опускается только в том случае, если тип значения, реализующий IDisposable , находится в выражении using , а не в каком-либо другом контексте.

Для получения дополнительной информации, пожалуйста, см. Оператор использования и типы одноразовых значений :

Некоторое время назад Ян Гриффитс писал о улучшение его класса TimedLock в котором он изменил его с класса на структура. Это изменение привело к тип значения, реализующий IDisposable. У меня был назойливый вопрос в глубине души в то время о котором я быстро забыл. В вопрос в том, не было бы примеров этого типа "получить коробку" при вызове Dispose?

А также О, нет! Только не TimedLock! :

Джон Сэндс указывает на недостаток в код, который я показал в недавнем блоге для использование тайм-аутов на замках без отказавшись от большей части удобства Ключевое слово C # lock .

7
ответ дан 8 December 2019 в 16:06
поделиться

Это дубликат Если моя структура реализует IDisposable, будет ли она помещена в коробку при использовании в операторе using?

ОБНОВЛЕНИЕ: Этот вопрос был темой моего блога в марте 2011 г. . Спасибо за отличный вопрос!

Ответ Эндрю Хейра правильный; Я просто хотел добавить интересную дополнительную заметку. Оптимизация, которую мы проводим, - использование ограниченного callvirt для пропуска бокса, когда это возможно, - фактически, строго говоря, является нарушением спецификации C #. В спецификации указано, что блок finally, который мы генерируем для ресурса типа значения, следующий:

     finally 
     {
         ((IDisposable)resource).Dispose();
     }

, который явно является преобразованием упаковки для типа значения. Можно строить надуманные сценарии, в которых видно отсутствие бокса в реализации.

(Спасибо Владимиру Решетникову за указание мне на это нарушение спецификации.

5
ответ дан 8 December 2019 в 16:06
поделиться

Методы экземпляра для типа значения принимают параметр this в качестве своего первого аргумента, аналогично тому, как это делают методы экземпляра для ссылочных типов. Однако параметр в этом случае является управляемым указателем на данные объекта, а не ссылкой на упакованный объект. Вы можете найти его в памяти следующим образом:

Unboxed object:
-----------------------------------------
|              DATA                     |
-----------------------------------------
 ^ managed pointer to struct

Boxed object:
------------------------------------------------------------
| GC/Object header |              [Boxed] DATA             |
------------------------------------------------------------
                    ^ The 'unbox' opcode gives a managed pointer to the boxed data
 ^ A *reference* to any instance of a reference type or boxed object, points here

DATA одинаковы в обоих случаях¹.

Методы экземпляра для типа значения ожидают управляемый указатель на данные , в частности , поэтому упаковка предметов не требуется. Как вы видите выше, код операции с ограничениями используется перед вызовом. Он сообщает среде выполнения, что следующая инструкция callvirt получает управляемый указатель на структуру ConsoleApplication2.Disposable вместо ссылки на объект, которую она обычно получает. При этом JIT может разрешить запечатанную перегрузку Dispose () , реализованную структурой, и вызвать ее напрямую, не упаковывая объект. Без префикса с ограничениями объект, переданный команде callvirt , должен был бы быть ссылкой на объект, поскольку стандартная процедура динамического разрешения виртуального вызова основана на том факте, что GC / Object заголовок всегда в ожидаемом месте - и да, это заставит упаковывать типы значений.

¹ Мы продолжим и пока проигнорируем Nullable .

3
ответ дан 8 December 2019 в 16:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: