为什么GetType返回System.Int32而不是Nullable

本文关键字:Int32 Nullable GetType 返回 System 为什么 | 更新日期: 2023-09-27 18:04:30

为什么这段代码的输出是System.Int32而不是Nullable<Int32> ?

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

为什么GetType返回System.Int32而不是Nullable<Int32>

GetType()object的一种方法。
要调用它,必须将Nullable<T>结构体装箱。

您可以在IL代码中看到:

//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

可空类型被CLR特殊处理;不可能有一个可空类型的盒装实例。
相反,将可空类型装箱将导致null引用(如果HasValue为false),或装箱后的值(如果有值)。

因此,box System.Nullable<System.Int32>指令得到的是盒装的Int32,而不是盒装的Nullable<Int32>

因此,GetType() 不可能永远返回Nullable<T>。 要更清楚地了解这一点,请查看以下代码:
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());
}
这个打印

编译时类型:System.Nullable ' 1[System.Int32]
运行时类型:系统。Int32

GetType()不是虚拟的,因此只在object上定义。因此,要进行调用,必须首先将Nullable<Int32>装箱。然而,空值有特殊的装箱规则,所以只有Int32值被装箱,这是报告的类型。

你不能框空

你可以这样做:

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

因为"5"的类型是int.

如果你想检测一个类型是否为空,以及底层的类型,使用如下:

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;
}
相关文章: