如何判断对象的类型是否为Nullable <t>使用反射?</t>

时间:2010-10-05 15:11:41

标签: .net reflection nullable

如果我有Type,是否有一些简单的方法可以告诉它使用Reflection表示可以为空的值类型?理想情况下比(

)更清洁(也更正确)
static bool IsNullable(Type type)
{
    return type.IsValueType && type.Name.StartsWith("Nullable");
}

2 个答案:

答案 0 :(得分:18)

type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)

您可能还会发现Nullable.GetUnderlyingType(Type nullableType)有用,可轻松获得您传递的T typeof(Nullable<T>)

答案 1 :(得分:7)

尽管@ theCoop的回答是正确的(在将代码放入你提供的方法的主体中没有从根本上错误的),但这里有一些巨大的问题。

Nullable<T>被运行时视为具有一些非常特殊语义的“特殊”类型。特别是,当Nullable<T>装箱时:

  1. 如果HasValue == true,它的行为就像一个盒装的T,使得无法通过限制代码来判断创建的对象是否是通过装箱T或拳击产生的Nullable<T> 。 取消装箱到TNullable<T>都是可能的。
  2. 如果HasValue == false,拳击只会返回null。取消装箱到T将取消,取消装箱到Nullable<T>将成功,HasValue == false
  3. 在任何一种情况下,boxedNullableObject.GetType()都不会显示该对象是通过拳击Nullable<T>.生成的。我无法想到任何其他表现出这种奇怪行为的值类型。

    例如,考虑:

    // Output: "System.Nullable`1[System.Int32]"
    Console.WriteLine(typeof(int?));
    
    
    object boxedNullableInt32WithValue = new int?(0);
    
    // Output: "System.Int32", NOT "System.Nullable`1[System.Int32]"
    Console.WriteLine(boxedNullableInt32WithValue.GetType()); 
    
    
    object boxedNullableInt32WithoutValue = new int?();
    
    // NullReferenceException is thrown
    Console.WriteLine(boxedNullableInt32WithoutValue.GetType()); 
    

    因此,编写如下方法:

    public static bool IsObjectANullableT(this object obj) { ... }

    是一个非常糟糕的主意。

    编辑:另一方面,我刚刚意识到有一种框架方法可以使用与@ theCoop的样本相同的技术来完成您所需的工作:Nullable.GetUnderlyingType

    用法:

    static bool IsNullable(Type type)
    {
        return Nullable.GetUnderlyingType(type) != null;
    }
    

    编辑:刚才看到@TheCoop在答案中提到了这一点。我的错误。