Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the assignment of the null literal to a System.Nullable<T> type get handled by .Net (C#)?

Tags:

c#

nullable

I was wondering if anyone knows how the C# compiler handles the following assignment:

int? myInt = null;

My assumption is that there is an implicit conversion performed, but I cannot figure out how the null literal assignment is handled. I dissasembled the System.Nullable object and found the implicit operator is overriden to this:

public static implicit operator T?(T value)  {
    return new T?(value);  
}

Once called this would try to fire the secondary constructor:

public Nullable(T value) {
    this.value = value;
    this.hasValue = true; 
}

Which is where my confusion comes into play... this.value is of some value type and cannot be null.

So, does anyone know how this "magic" takes place... or am I wrong in assuming that the secondary constructor is called? Does the default constructor get called because the compiler knows that it cannot match the second contructor's signature with the null literal (resulting in myInt being assigned to a new "null" Nullable)?

like image 299
Albert Oldfield Avatar asked Jan 23 '23 17:01

Albert Oldfield


2 Answers

The statement:

int? myInt = null;

Gets compiled as:

  .locals init (valuetype [mscorlib]System.Nullable`1<int32> V_0)
  IL_0000:  ldloca.s   V_0
  IL_0002:  initobj    valuetype [mscorlib]System.Nullable`1<int32>

Which, according to the MSDN, means «Initialize each field of the value type at a specified address to a null reference or a 0 of the appropriate primitive type.»

So there's no constructor or conversion here. HasValue will return false, and trying to get its Value will throw an InvalidOperationException. Unless you use GetValueOrDefault of course.

like image 143
Jb Evain Avatar answered Mar 30 '23 00:03

Jb Evain


What really happens is that when you assign null to the nullable type instance, the compiler simply creates a new instance of T?, using the default constructor (the initobj IL instruction on Jb answer), so the following two lines are equivalent:

int? a = null;
Nullable<int> b = new Nullable<int>();

object.Equals(a,b); // true

Therefore you cannot do this:

Nullable<int> c = new Nullable<int>(null);

Something similar happens then you compare a nullable type to null:

if (a == null)
{
  // ...
}

Behind the scenes it just does a call to the a.HasValue property.

like image 45
Christian C. Salvadó Avatar answered Mar 30 '23 00:03

Christian C. Salvadó