typeof int?
为什么是Int32
?
int? x = 1;
Console.WriteLine(x.GetType().Name);
如果一切正常,那么使用Nullable.GetUnderlyingType
有什么用呢?
调用 GetType()
会将变量装箱。CLR有一个特殊规则,Nullable<T>
被装箱为 T
。因此,x.GetType
将返回 Int32
而不是 Nullable<Int32>
。
int? x = 1;
x.GetType() //Int32
typeof(int?) //Nullable<Int32>
由于包含 null
的 Nullable
会被装箱成 null
,因此以下代码将抛出异常:
int? x = null;
x.GetType() //throws NullReferenceException
基于可空类型的对象只有在对象非空时才会被装箱。如果
HasValue
为false
,则对象引用被赋值为null
而不是被装箱。如果对象非空——即
HasValue
为true
——那么装箱会发生,但只有基于可空对象的底层类型才会被装箱。对非空的可空值类型进行装箱会使值类型本身被装箱,而不是包装值类型的System.Nullable<T>
被装箱。
这个例子有点混乱,因为:
int? x = 1;
创建一个Nullable<int>
,就像您所期望的一样;然而:
Type type = x.GetType();
调用非虚方法object
,这个方法并没有被重写,因此这是一个装箱操作;而Nullable<T>
有特殊的装箱规则:
null
即:
int? x = 1;
int y = 1;
将方框内的内容完全转换为同样的东西。
因此,您正在将 typeof(int)
传递给 GetUnderlyingType
。
一个更具说明性的例子是在使用反射时:
class Foo {
public int? Bar {get;set;}
}
...
Type type = typeof(Foo); // usually indirectly
foreach(var prop in type.GetProperties()) {
Type propType = prop.PropertyType,
nullType = Nullable.GetUnderlyingType(propType);
if(nullType != null) {
// special code for handling Nullable<T> properties;
// note nullType now holds the T
} else {
// code for handling other properties
}
}
null
,则两者之间存在轻微差异。在前者中,对象将被装箱,并在生成的“null”引用上调用方法,这会导致运行时抛出NullReferenceException
,而在后者中,Value
属性(不需要装箱)将检查并在值确实为null时抛出InvalidOperationException
。 - Mehrdad AfshariNullable<T>
的大多数操作,它都会这样做。 - Marc Gravell这是用于当你不知道它是Int32
时的情况。
public Type GetNullableUnderlyingType<T>(Nullable<T> obj)
where T : struct
{
return Nullable.GetUnderlyingType(typeof(Nullable<T>));
}
在这里,您可以传递任何Nullable
对象并使其返回底层类型。
当你写 int?
时,就好像你写了 Nullable<int>
。我认为这是你要找的类型。
public static void SomeMethod<T>(T argument)
{
if(Nullable.GetUnderlyingType(typeof(T) != null)
{
/* special case for nullable code go here */
}
else
{
/* Do something else T isn't nullable */
}
}
了解这一点非常重要,因为某些非常便宜的东西在可空类型上可能会非常昂贵。例如,if(argument == null)
通常非常便宜,但在Nullable<T>
上的通用方法中执行时,必须将argument
装箱以获取空引用。您最好使用EqualityComparer<T>.Default
,这会减慢其他所有操作,但使可空类型不受影响。
x.GetType().Name
可以得到Int32
,那么我们为什么需要Nullable.GetUnderlyingType()来找出它是Int32
。 - decyclonetypeof(int?)
是System.Nullable<Int32>
。 - IS4