首先声明:本文与如何检查对象是否可为空不是重复的问题。或者说,那个问题并没有提供有用的答案,作者进一步阐述实际上是在问如何确定给定类型(例如从MethodInfo.ReturnType返回的类型)是否可为空。
然而,这很容易。难点在于确定在编译时未知类型的运行时对象是否为可空类型。请考虑以下情况:
这不按预期工作,因为
总之,问题不在于确定类型是否可为空,而是首先获取该类型。 因此,我的挑战是:如何确定运行时对象(上述示例中的obj参数)是否可为空?给我惊喜吧 :)
然而,这很容易。难点在于确定在编译时未知类型的运行时对象是否为可空类型。请考虑以下情况:
public void Foo(object obj)
{
var bar = IsNullable(obj);
}
private bool IsNullable(object obj)
{
var type = obj.GetType();
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
// Alternatively something like:
// return !(Nullable.GetUnderlyingType(type) != null);
}
这不按预期工作,因为
GetType()
调用会导致装箱操作(https://msdn.microsoft.com/zh-cn/library/ms366789.aspx),并返回基础值类型而非可空类型。因此,IsNullable()
总是返回false。
现在,以下技巧使用类型参数推断来获取(未装箱的)类型:private bool IsNullable<T>(T obj)
{
var type = typeof(T);
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
}
这看起来一开始很有前途。然而,类型参数推断仅在编译时已知对象类型时才起作用。所以:
public void Foo(object obj)
{
int? genericObj = 23;
var bar1 = IsNullable(genericObj); // Works
var bar2 = IsNullable(obj); // Doesn't work (type parameter is Object)
}
总之,问题不在于确定类型是否可为空,而是首先获取该类型。 因此,我的挑战是:如何确定运行时对象(上述示例中的obj参数)是否可为空?给我惊喜吧 :)