Подтвердить что ты не робот

Где в памяти хранятся типы с нулевым значением?

Возможно, это вопрос о типах с нулевым значением.

Где указаны типы значений с нулевым значением (int?...), хранящиеся в памяти? Сначала я подумал, что это достаточно ясно, поскольку Nullable<T> - это структура, а это типы значений. Затем я нашел статью Джона Скита "" Память в .NET", в которой говорится:

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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

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

Ссылка MSDN на Nullables

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

Ответ 3

Nullables только притворяется нулевым:

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);

Ответ 4

В дополнение к ответу Кевина: компилятор знает о типах Nullable и изменяет проверку ==null на вызов .HasValue.