Где в памяти nullable сохраненные типы?

Это - возможно, следование до вопроса о nullable типах.

Где точно nullable типы значения (int?...) сохраненный в памяти? Сначала я думал, что это достаточно ясно, как Nullable структура, и это - типы значения. Затем я нашел статью "Memory in.NET" Jon Skeet, в которой говорится:

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

Я немного смущен после чтения этого оператора. Так скажем, я имею int? a = null;. Как int обычно тип значения, сохраненный так или иначе в структуре Nullable в стеке (я использовал "обычно", потому что я не знаю то, что происходит с типом значения, когда это становится nullable)? Или что-либо еще происходит здесь - возможно, в "куче"?

32
задан Community 23 May 2017 в 12:09
поделиться

4 ответа

Во-первых, Nullable - это просто сокращение для чего-то вроде:

struct Nullable<T> 
{
    bool hasValue;
    T value;
}

Плюс ко всем конструкторам, методам доступа и так далее. Вот и все - int, допускающий значение NULL, - это обычный int плюс флаг, который говорит, является ли int нулевым или нет. Все остальное - магия компилятора, которая рассматривает «null» как допустимое значение; все, что «null» делает с типом, допускающим значение NULL, делает вас одной из тех структур с флагом, установленным в значение false.

Итак, теперь, когда у нас есть это в стороне, ваш вопрос: «Куда они уходят в памяти»? Они размещаются в том же месте, что и любые другие структуры в памяти: где среда выполнения и компилятор считают лучшим местом с учетом времени жизни памяти.

Большинство структур помещаются в кучу. Любой, кто говорит вам, что «структуры всегда помещаются в стек», на самом деле не знает, о чем они говорят; в нашей документации об этом не говорится, и это неправда. Структуры размещаются во временном пуле памяти, также известном как «стек», только когда они являются локальными переменными или временными библиотеками, а локальные переменные не являются закрытыми внешними переменными анонимного метода или лямбда-выражения, а локальные переменные не находятся в итераторе. блокировать. Все остальные структуры в нашей реализации помещаются в кучу.

Отметим также, что нет никаких требований, чтобы реализация CLI использовала «стек» для создания своего временного пула. Например, классический диспетчер памяти JScript хранит свой временный пул в куче.(Хотя, конечно, среда выполнения JScript не является реализацией интерфейса командной строки; я просто указываю, что можно разработать управляемую машину времени выполнения, которая не помещает никаких пользовательских данных в «стек».) Логически это структура данных стека. , но эта структура данных не хранится в «стеке», это просто структура стека, размещенная в куче.

Я должен спросить: какое тебе дело? CLR управляет памятью от вашего имени. Почему вас волнует, куда идут типы, допускающие значение NULL? Они едут туда, где живут достаточно долго, чтобы быть вам полезными; вам не о чем беспокоиться.

74
ответ дан 27 November 2019 в 20:05
поделиться

См. Комментарий Эрика о том, где хранятся структуры. Это гораздо более основательно (и правильно), чем то, что я опубликовал.

Принцип работы заключается в том, что обнуляемое значение имеет логическое значение, которое сообщает, установлено ли значение. Технически вы правы, nullable (int, bool) и т.д. на самом деле не является нулевым. у него есть значение по умолчанию. просто теперь тип, допускающий значение NULL, имеет логическое значение, которое вы можете проверить и увидеть, установлено ли это значение или это просто значение по умолчанию. = и == переопределяются для установки соответствующих значений при присвоении ему null (и значения) для него

Ссылка MSDN на Nullables

Еще одна ссылка, описывающая, как работают значения NULL:
http://www.markzhou.com/blog/post/2010/01/27/Why-can-assign-e2809cnulle2809d-to-nullable-types.aspx

7
ответ дан 27 November 2019 в 20:05
поделиться

В дополнение к ответу Кевина: компилятор знает о типах, допускающих значение NULL, и меняет проверку == null на вызов ".HasValue".

2
ответ дан 27 November 2019 в 20:05
поделиться

Nullables только притворяются null:

int? a = null;
Debug.Assert((a == null) == (!a.HasValue));

Компилятор соучаствует в этой шараде. Одним из забавных следствий этого является следующее:

Nullable<double> b = new Nullable<double>();
Debug.Assert(b == null); //I'm null upon construction!

Они также получают специальную поддержку бокса:

int? c = null;
Object d = c;
Debug.Assert(d == null);
Debug.Assert(!c.HasValue);
3
ответ дан 27 November 2019 в 20:05
поделиться
Другие вопросы по тегам:

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