5

I am trying to understand one thing in this code:

Nullable<Int32> x = 5;
Nullable<Int32> y = null;
Console.WriteLine("x: HasValue={0}, Value={1}",  x.HasValue, x.Value);
Console.WriteLine("y: HasValue={0}, Value={1}",  y.HasValue, y.GetValueOrDefault());

And Output is:

x: HasValue=True, Value=5
y: HasValue=False, Value=0

And the thing that I don't understand when you pass null to y, I believe it calls public static implicit operator Nullable<T>(T value) but the definition of this method initializes a new struct passing value which is assigned null however constructor method doesn't check whether it is null or not so it can assign default(T) to value.

How come we can even assign null to struct here and it works fine?

Can you guys what I am missing out here? I don't understand how it just bypassed null and returned default value.

Nullable code inner definition:

http://codepaste.net/gtce6d

Tarik
  • 79,711
  • 83
  • 236
  • 349
  • any reason why you aren't using the built in `Nullable` struct? – Daniel A. White Jun 03 '12 at 01:08
  • I am just learning the internal structure of nullable types. – Tarik Jun 03 '12 at 01:16
  • As a sidenote: Your `Equals` implementation is broken. If both sides are your custom nullable, and both are custom-null, it will return false, but should return true. | It also shouldn't compile, because you can't have initializers on instance fields for structs. – CodesInChaos Jun 03 '12 at 01:57
  • @CodeInChaos: It is taken from CLR with C# 3.0 though. – Tarik Jun 03 '12 at 01:58
  • Oh in that case, it works, since there is sufficent compiler and runtime magic in the background. And the code you give isn't any real code, it's just an approximation. – CodesInChaos Jun 03 '12 at 02:01
  • #CodeInChaos: You mean it doesn't work? Well I didn't work in real environment though. – Tarik Jun 03 '12 at 02:57
  • CodeInChaos is wrong about the code not working -- it does work. However, he is right that it works because the compiler and CLR have special magic to handle `Nullable<>` types. Ultimately, that's probably the answer to your question. – Gabe Jun 03 '12 at 05:43
  • Both the compiler and the jitter have built-in knowledge of Nullable<> and give it special treatment. You cannot get them to treat your own MyNullable<> type the same way. – Hans Passant Jun 03 '12 at 07:37

4 Answers4

6

believe it calls public static implicit operator Nullable(T value)

No it doesn't, because T is Int32 in this case, and null is not an Int32. It just leaves the y variable default, which means for a struct that all bytes are 0. This results in a struct that has a HasValue that returns false.

You can't really pass null to a struct, but the C# compiler is converting this for you to a default initalization.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • Then what makes this struct `Nullable` and `Int32` not? How come you can assign `null` which doesn't throw an error yet `Int32` does? It is because it has `implicit` overloading? – Tarik Jun 03 '12 at 01:30
  • 2
    What makes it nullable is that you defined is at nullable. Nullable struct has some compiler magic behind to make it easier to use. – TomTom Jun 03 '12 at 06:44
1

The default is assigned in the constructor called by new Nullable<T>(value); (Line 40)

Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92
1

My guess is that assigning null to a nullable calls the default constructor. That is the only possible way for hasValue to remain false.

Dave Cousineau
  • 12,154
  • 8
  • 64
  • 80
  • Can't they have some `if` statements to check whether they should change the HasValue property? – SimpleVar Jun 03 '12 at 01:22
  • @YoryeNathan maybe they could, but there aren't any. actually, although it doesn't say `readonly` on the fields, the struct is designed to be immutable. hasValue and value are both only ever set in constructors; so yeah, while it's not shown in the code, the default constructor is the only way to get a value of `null`. – Dave Cousineau Jun 03 '12 at 01:30
  • But `struct` cannot have parameterless constructor. How come it calls it? http://stackoverflow.com/questions/575901/why-struct-can-not-have-parameterless-constructor – Tarik Jun 03 '12 at 01:34
  • @Braveyard If I recall, `struct`s have an *implicit* default constructor that you cannot modify. It always sets everything to their default values. While the code snippet shows the fields being initialized explicitly, that would actually give you a compile error. I'm guessing that the code viewing tool is just showing the compiler's default initializers. – Dave Cousineau Jun 03 '12 at 01:47
1

A Nullable<T> is simply a structure which has a boolean field indicating whether it has a value, and a field which (if the first field is true) indicates what that value is. It isn't really possible to set any structure to null, and a Nullable<T> is no exception. Instead, the compiler translates a request to set a Nullable<T> to null as a request to set the "has value" field (reflected in property HasValue) to false and set the "actual value" field (reflected in property Value) to the default for its type.

Personally, I think pretending that a Nullable<T> where HasValue is false is null is more confusing than helpful, but I am not Microsoft. I would think it would have been more helpful for each Nullable<T> type to have a static property Nullable<T>.Null (which would be equivalent to default(Nullable<T>), but the behavior of Nullable<T> is sufficiently well-established I doubt it will ever change.

supercat
  • 77,689
  • 9
  • 166
  • 211