tags:

views:

360

answers:

4

This is maybe a follow up to question about nullable types.

Where exactly are nullable value types (int?...) stored in memory? First I thought it's clear enough, as Nullable<T> is struct and those are value types. Then I found Jon Skeet's article "Memory in .NET", which says:

Note that a value type variable can never have a value of null - it wouldn't make any sense, as null is a reference type concept, meaning "the value of this reference type variable isn't a reference to any object at all".

I am little bit confused after reading this statement. So let's say I have int? a = null;. As int is normally a value type, is it stored somehow inside struct Nullable<T> in stack (I used "normally" because I don't know what happens with value type when it becomes nullable)? Or anything else happens here - perhaps in heap?

+6  A: 

See Eric's comment about where structs are stored. It is much more thorough (and correct) than what I posted.

The way it works is that the nullable has a boolean that says whether or not the value has been set. Technically you are correct the nullable (int, bool) etc isn't actually null. it has a default value. it's just that now the nullable type has a boolean you can check and see if that value was set or it is just it's default value. The = and == are overridden to set the appropriate values when assigning null (and a value) to it

MSDN link to Nullables

Another link describing how nullables work:
http://www.markzhou.com/blog/post/2010/01/27/Why-can-assign-e2809cnulle2809d-to-nullable-types.aspx

Kevin
Structs are not always stored on the stack. A correct statement is "local variables of struct type which are not closed-over outer variables of an anonymous method or lambda expressions and are not in an iterator block are stored on the stack in the Microsoft implementation of the desktop CLR." There is no requirement that there be a data structure called "the stack" or that all structs be stored on it. Structs which are fields of a class or locals in an iterator block or outer variables are stored on the heap.
Eric Lippert
As always, thank you for the clarification.
Kevin
+2  A: 

In addition to Kevin's answer: the compiler knows about Nullable types and changes an ==null check into a call to ".HasValue".

Hans Kesting
+3  A: 

Nullables only pretend to be null:

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

The compiler is complicit in this charade. One funny consequence of this is the following:

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

They also get special boxing support:

int? c = null;
Object d = c;
Debug.Assert(d == null);
Debug.Assert(!c.HasValue);
Dan Bryant
You forgot the most magic of all (one you can't emulate with operator overloading): operator lifting.
Martinho Fernandes
+17  A: 

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.

Eric Lippert
A very easy +1 from me. Thanks for exhausting answer. I care because I'm curious. I think (maybe naively enough) it's valuable information to know what actually happens behind my code. I don't want to end up coding something that does god-knows-what magic.
Ondrej Slinták
@Ondrej, if you think the Nullable compiler support is magic, try writing an IEnumerable method with yield returns using a lambda expression containing a closure. Open up the resulting program in ildasm and take a look at what the compiler did for you under the covers.
Dan Bryant
I was speaking generally. Not that I actually think that everything in programming is a magic. I am aware that there are most likely more hard-to-understand pieces of code than this is.
Ondrej Slinták
@Dan: Ah... it hurts! My eyes!
Martinho Fernandes
a question to gain understanding should not be responded to with "why do you care?"
wcpro
@wcpro: Of course it should. Understanding *why* a question is being asked is *absolutely key* to giving an answer that meets the actual needs of the questioner! If the questioner is asking out of curiosity, that's one thing. **If the questioner is going to be making a technical or business decision on the basis of the answer that is an entirely other thing**. It is very important to know why someone wants to know so that the answer can be tailored to give them the right information to make that decision effectively.
Eric Lippert