Прежде всего, Nullable<int>
это просто сокращение для чего-то вроде:
struct Nullable<T>
{
bool hasValue;
T value;
}
Плюс все конструкторы, аксессоры и так далее. Вот и все - обнуляемый int - это обычный int плюс флаг, который говорит, является ли int нулевым или нет. Все остальное - магия компилятора, которая рассматривает «ноль» как допустимое значение; все, что "null" делает с обнуляемым типом, делает вас одной из тех структур с флагом, установленным в false.
Так что теперь, когда у нас есть это вне пути, ваш вопрос "куда они идут в памяти"? Они идут в том же месте, что и любые другие структуры в памяти: где среда выполнения и компилятор считают лучшим местом, учитывая время жизни памяти.
Большинство структур идут в кучу. Любой, кто говорит вам, что «структуры всегда идут в стек», на самом деле не знает, о чем они говорят; наша документация не говорит об этом, и это не так. Структуры отправляются только во временный пул памяти, иначе говоря, «стек», когда они являются локальными переменными или временными переменными, и локальные переменные не являются закрытыми внешними переменными анонимного метода или лямбды, а локальные переменные не находятся в итераторе блок. Все другие структуры идут в кучу в нашей реализации.
Обратите также внимание, что нет требования, чтобы реализация CLI использовала «стек» для создания своего временного пула. Например, классический диспетчер памяти JScript сохраняет свой временный пул в куче. (Хотя, конечно, движок JScript не является реализацией CLI; я просто указываю, что можно разработать управляемый движок, который вообще не помещает пользовательские данные в «стек».) Логически это структура данных стека. , но эта структура данных не хранится в «стеке», это просто структура стека, выделенная в куче.
Я должен спросить: почему тебя это волнует? CLR управляет памятью от вашего имени. Почему тебя волнует, куда идут обнуляемые типы? Они идут туда, где живут достаточно долго, чтобы быть полезными для вас; вам не нужно беспокоиться об этом.