How CLR can bypass throwing error when assigning a

2019-06-22 00:07发布

问题:

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

回答1:

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.



回答2:

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



回答3:

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



回答4:

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.