Why is the output of this snippet System.Int32
instead of Nullable<Int32>
?
int? x = 5; Console.WriteLine(x.GetType());
Here, T represents the data type of the variable. The following statement would not compile as you cannot assign a null value to a value type. Int32 i = null; To assign a null value to a value type, you need to take advantage of a nullable type as shown in the code snippet below.
The default value of a bool variable in C# is false (reference). Therefore, the HasValue property of a default Nullable<T> instance is false ; which in turn makes that Nullable<T> instance itself act like null .
As you know, a value type cannot be assigned a null value. For example, int i = null will give you a compile time error. C# 2.0 introduced nullable types that allow you to assign null to value type variables. You can declare nullable types using Nullable<t> where T is a type.
GetType()
is a method of object
.
To call it, the Nullable<T>
struct must be boxed.
You can see this in the IL code:
//int? x = 5; IL_0000: ldloca.s 00 IL_0002: ldc.i4.5 IL_0003: call System.Nullable<System.Int32>..ctor //Console.WriteLine(x.GetType()); IL_0008: ldloc.0 IL_0009: box System.Nullable<System.Int32> IL_000E: callvirt System.Object.GetType IL_0013: call System.Console.WriteLine
Nullable types are treated specially by CLR; it is impossible to have a boxed instance of a nullable type.
Instead, boxing a nullable type will result in a null reference (if HasValue
is false), or the boxed value (if there is a value).
Therefore, the box System.Nullable<System.Int32>
instruction results in a boxed Int32
, not a boxed Nullable<Int32>
.
Therefore, it is impossible for GetType()
to ever return Nullable<T>
.
To see this more clearly, look at the following code:
static void Main() { int? x = 5; PrintType(x); } static void PrintType<T>(T val) { Console.WriteLine("Compile-time type: " + typeof(T)); Console.WriteLine("Run-time type: " + val.GetType()); }
This prints
Compile-time type: System.Nullable`1[System.Int32]
Run-time type: System.Int32
GetType()
isn't virtual, and is thus defined only on object
. As such, to make the call, the Nullable<Int32>
must first be boxed. Nullables have special boxing rules, though, so only the Int32
value is boxed, and that's the type reported.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With