为什么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()
是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;
}