¿Por qué GetType devuelve System.Int32 en lugar de Nullable ?

¿Por qué el resultado de este fragmento es System.Int32 lugar de Nullable ?

 int? x = 5; Console.WriteLine(x.GetType()); 

GetType() es un método de object .
Para llamarlo, la Nullable debe estar encuadrada.

Puedes ver esto en el código IL:

 //int? x = 5; IL_0000: ldloca.s 00 IL_0002: ldc.i4.5 IL_0003: call System.Nullable..ctor //Console.WriteLine(x.GetType()); IL_0008: ldloc.0 IL_0009: box System.Nullable IL_000E: callvirt System.Object.GetType IL_0013: call System.Console.WriteLine 

Los tipos anulables son tratados especialmente por CLR; es imposible tener una instancia en caja de un tipo que admite nulos.
En cambio, el boxeo de un tipo anulable dará como resultado una referencia nula (si HasValue es falso), o el valor HasValue (si hay un valor).

Por lo tanto, la instrucción de box System.Nullable da como resultado un Int32 Nullable , no un Nullable .

Por lo tanto, es imposible que GetType() devuelva Nullable alguna vez .

Para ver esto más claramente, mira el siguiente código:

 static void Main() { int? x = 5; PrintType(x); } static void PrintType(T val) { Console.WriteLine("Compile-time type: " + typeof(T)); Console.WriteLine("Run-time type: " + val.GetType()); } 

Esto imprime

Tipo de tiempo de comstackción: System.Nullable`1 [System.Int32]
Tipo de tiempo de ejecución: System.Int32

GetType() no es virtual y, por lo tanto, se define solo en el object . Como tal, para realizar la llamada, el Nullable primero debe estar encuadrado. Sin embargo, Nullables tiene reglas especiales de boxeo, por lo que solo el valor Int32 está encuadrado, y ese es el tipo informado.

No puedes boxear con un nulo.

Podrías hacer algo como esto:

 public static Type GetCompilerType(this T @object) { return typeof (T); } int? x = 5; Console.WriteLine(x.GetCompilerType()); // prints: // System.Nullable`1[System.Int32] 

Porque el tipo de “5” es int.

Si desea detectar si un tipo es anulable, y el tipo subyacente, use algo como esto:

 public static Type GetActualType(Type type, out bool isNullable) { Type ult = Nullable.GetUnderlyingType(type); if (ult != null) { isNullable = true; return ult; } isNullable = false; return type; }