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

Dan*_*Tao 9 .net reflection nullable

如果我有一个Type,是否有一些简单的方法来告诉它使用Reflection代表一个可以为空的值类型?理想情况下,比以下更清洁(也更正确):

static bool IsNullable(Type type)
{
    return type.IsValueType && type.Name.StartsWith("Nullable");
}
Run Code Online (Sandbox Code Playgroud)

the*_*oop 18

type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)
Run Code Online (Sandbox Code Playgroud)

你也可以找到Nullable.GetUnderlyingType(Type nullableType)有用的,很容易得到Ttypeof(Nullable<T>)你通过.


Ani*_*Ani 7

虽然@ theCoop的答案是正确的(将代码放入你提供的方法体中并没有根本的错误),但这里有一些巨大的问题.

Nullable<T>被运行时视为具有一些非常特殊语义的"特殊"类型.特别是当a Nullable<T>盒装时:

  1. 如果HasValue == true,它的行为就像一个盒装T,使得下游代码无法判断创建的对象是否是通过拳击T或拳击生成的Nullable<T>.取消装箱T并且Nullable<T>都是可能的.
  2. 如果HasValue == false,拳击只是返回null.拆箱T将抛出,拆箱Nullable<T>将成功,为此 HasValue == false.

在任何一种情况下,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()); 
Run Code Online (Sandbox Code Playgroud)

因此,编写如下方法:

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

是一个非常糟糕的主意.

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

用法:

static bool IsNullable(Type type)
{
    return Nullable.GetUnderlyingType(type) != null;
}
Run Code Online (Sandbox Code Playgroud)

编辑:刚才看到@TheCoop在他的回答中也提到了这一点.我的错.

  • 它也很有用,因为在看到这个之前我没有看到另一个问题.我今天学到了新东西.:) (2认同)