Распаковывание просто возвращает указатель на значение в помещенном в коробку объекте на "куче"?

Я эта статья MSDN Magazine, состояния автора (шахта акцента):

Обратите внимание, что упаковка всегда создает новый объект и копирует биты распакованного значения в объект. С другой стороны, распаковывание просто возвращает указатель на данные в помещенном в коробку объекте: никакая копия памяти не происходит. Однако обычно имеет место, что Ваш код заставит данные, на которые указывает распакованная ссылка быть скопированными так или иначе.

Я смущен предложением, которое я имею полужирный и предложение, которое следует за ним. От всего остального я читал, включая эту страницу MSDN, я прежде никогда не слышал, что распаковывание просто возвращает указатель на значение на "куче". У меня создалось впечатление, что распаковывание приведет к Вам имеющий переменную, содержащую копию значения на стеке, когда Вы начали. В конце концов, если моя переменная содержит "указатель на значение на "куче"", затем у меня нет типа значения, у меня есть указатель.

Кто-то может объяснить, что это означает? Был автор на трещине? (Существует по крайней мере еще одна явная ошибка в статье). И если это верно, каковы случаи, где "Ваш код заставит данные, на которые указывает распакованная ссылка быть скопированными так или иначе"?

Я просто заметил, что статье почти 10 лет, поэтому возможно, это - что-то, что изменилось очень вначале в жизни .NET.

9
задан Igby Largeman 5 June 2010 в 00:53
поделиться

2 ответа

Статья точная. Однако в ней говорится о том, что действительно происходит, а не о том, как выглядит IL, который генерирует компилятор. В конце концов, программа .NET никогда не выполняет IL, она выполняет машинный код, который генерируется из IL компилятором JIT.

И опкод unbox действительно генерирует код, который производит указатель на биты на куче, представляющие значение типа value. JIT генерирует вызов небольшой вспомогательной функции в CLR с именем "JIT_Unbox". clr\src\vm\jithelpers.cpp, если вы получили исходный код SSCLI20. Функция Object::GetData() возвращает указатель.

Оттуда значение чаще всего сначала копируется в регистр процессора. Затем оно может где-то храниться. Это не обязательно должен быть стек, это может быть член объекта ссылочного типа (куча gc). Или статическая переменная (куча загрузчика). Или она может быть помещена в стек (вызов метода). Или регистр процессора может быть использован как есть, когда значение используется в выражении.

Во время отладки щелкните правой кнопкой мыши на окне редактора и выберите "Go To Disassembly", чтобы увидеть машинный код.

7
ответ дан 4 December 2019 в 15:12
поделиться

Боксирование - это акт приведения экземпляра типа значения к экземпляру типа ссылки (либо объекту, либо интерфейсу), а ссылочные типы размещаются на куче.

Согласно "C# 4.0 in a Nutshell": " ... unboxing copies содержимое объекта обратно в экземпляр типа значения", а это подразумевает выделение на стеке.

В статье, на которую вы ссылаетесь, автор утверждает:

public static void Main() {

   Int32 v = 5;    // Create an unboxed value type variable
   Object o = v;   // o refers to a boxed version of v
   v = 123;        // Changes the unboxed value to 123

   Console.WriteLine(v + ", " + (Int32) o);    // Displays "123, 5"
}

Из этого кода вы можете угадать, сколько операций боксирования? Возможно, вы будете удивитесь, узнав, что ответ три! Давайте проанализируем код внимательно, чтобы понять, что что происходит. Во-первых, создается тип значения Int32 без коробки (v), который инициализируется значением 5. Затем создается ссылочный тип Object (o), который хочет указать на v. Но ссылочные типы всегда должны указывать на объекты в куче, поэтому C# сгенерировал соответствующий IL-код, чтобы поместить v и сохранил адрес упакованной версии v в o. Теперь 123 распаковывается и данные по ссылке копируются в небоксовый тип значения v; это не имеет никакого не влияет на ящичную версию v, поэтому ящичная версия сохраняет свое значение 5. Обратите внимание, что в этом примере показано, как o раскрывается (что возвращает указатель на данные в o), а затем данные в o копируются в память для сохранения в распакованном значении type v.

1
ответ дан 4 December 2019 в 15:12
поделиться
Другие вопросы по тегам:

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