为什么GetType返回System.Int32而不是Nullable ?
为什么这个片段System.Int32
的输出而不是Nullable
?
int? x = 5; Console.WriteLine(x.GetType());
GetType()
是一个object
的方法。
要调用它,必须将Nullable
结构框装箱。
你可以在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
可空类型由CLR专门处理; 不可能有一个可空类型的盒装实例。
相反,装入可空类型将导致空引用(如果HasValue
为false)或盒装值(如果有值)。
因此, box System.Nullable
指令产生一个盒装的Int32
,而不是一个盒装的Nullable
。
因此, GetType()
不可能返回Nullable
。
要更清楚地看到这一点,请查看以下代码:
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()); }
这打印
编译时类型:System.Nullable`1 [System.Int32]
运行时类型:System.Int32
GetType()
不是虚拟的,因此仅在object
上定义。 因此,要进行调用,必须首先Nullable
。 Nullables有特殊的装箱规则,因此只有Int32
值被装箱,这就是报告的类型。
你不能装空。
你可以这样做:
public static Type GetCompilerType(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; }