【发布时间】:2011-10-19 09:28:21
【问题描述】:
为什么这个sn-p的输出是System.Int32而不是Nullable<Int32>?
int? x = 5;
Console.WriteLine(x.GetType());
【问题讨论】:
标签: c# .net reflection nullable gettype
为什么这个sn-p的输出是System.Int32而不是Nullable<Int32>?
int? x = 5;
Console.WriteLine(x.GetType());
【问题讨论】:
标签: c# .net reflection nullable 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 特殊处理;不可能有可空类型的盒装实例。
相反,对可空类型进行装箱将导致空引用(如果 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]
运行时类型:System.Int32
【讨论】:
GetType() 不是虚拟的,因此仅在object 上定义。因此,要拨打电话,Nullable<Int32> 必须首先被装箱。不过,可空对象有特殊的装箱规则,因此只有 Int32 值被装箱,这就是报告的类型。
【讨论】:
int 变量装箱以调用GetType()。由于总是要加载重要的类型,因此这可能是空间/文档一致性的让步。也许 Eric Lippert 可以提供更多的启示。
GetType() 对于sealed 类型没有真正意义,因为您可以只使用typeof()。 Nullable<T> 和所有 structs 一样,是隐式密封的。如果调用GetType() 确实没有意义,当然,如果没有理由不这样做,它会起作用,但仅此而已,不要期望在优化方面付出太多努力。
你不能 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]
【讨论】:
因为“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;
}
【讨论】:
x 是 int?。
int? 变量中。您看到int 的原因是int? 被装箱到int。