First off, Nullable<int>
is just a shorthand for something like:
struct Nullable<T>
{
bool hasValue;
T value;
}
Plus all the constructors, accessors, and so on. That's all it is -- a nullable int is an ordinary int plus a flag that says whether the int is null or not. All the rest is compiler magic that treats "null" as a valid value; all "null" does with a nullable type is makes you one of those structs with the flag set to false.
So now that we have that out of the way, your question is "where do they go in memory"? They go the same place that any other structs go in memory: where the runtime and compiler believe to be the best place given the lifetime of the memory.
Most structs go on the heap. Anyone who tells you that "structs always go on the stack" doesn't actually know what they are talking about; our documentation does not say that and it is not true. Structs only go on the temporary memory pool, aka "the stack", when they are local variables or temporaries, and the local variables are not closed-over outer variables of an anonymous method or lambda, and the local variables are not in an iterator block. All other structs go on the heap in our implementation.
Note also that there is no requirement whatsoever that an implementation of the CLI use "the stack" to make their temporary pool. The classic JScript memory manager, for example, stores its temporary pool on the heap. (Though of course the JScript runtime engine is not an implementation of the CLI; I'm merely pointing out that one can design a managed runtime engine that puts no user data whatsoever on "the stack".) Logically it is a stack data structure, but that data structure is not store on "the" stack, it's just a stack structure allocated on the heap.
I have to ask: why do you care? The CLR manages memory on your behalf. Why do you care where nullable types go? They go where they live long enough to be useful to you; you don't have to worry about that.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…