为什么此代码段System.Int32
的输出代替Nullable<Int32>
?
int? x = 5;
Console.WriteLine(x.GetType());
答案 0 :(得分:29)
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
Nullable类型由CLR专门处理;有一个可以为空的类型的盒装实例是不可能的
相反,装箱可空类型将导致空引用(如果HasValue
为假)或盒装值(如果有值)。
因此,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]
运行时类型:System.Int32
答案 1 :(得分:8)
GetType()
不是虚拟的,因此仅在object
上定义。因此,要进行通话,必须首先装箱Nullable<Int32>
。 Nullables有特殊的装箱规则,所以只有Int32
值被装箱,这就是报告的类型。
答案 2 :(得分:4)
你不能box可以为空。
你可以这样做:
public static Type GetCompilerType<T>(this T @object)
{
return typeof (T);
}
int? x = 5;
Console.WriteLine(x.GetCompilerType());
// prints:
// System.Nullable`1[System.Int32]
答案 3 :(得分:1)
因为“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;
}