通过反射检测可空类型

时间:2011-05-17 05:59:00

标签: c# reflection nullable

令人惊讶的是,以下代码未通过Assert:

int? wtf = 0;
Assert.IsType<Nullable<int>>(wtf);

所以只是出于好奇,你怎么能确定给定的实例是否是Nullable&lt;&gt;对象与否?

6 个答案:

答案 0 :(得分:49)

首先,Nullable<T>是一个结构,因此没有对象。你不能调用GetType(),因为它会设置值(此时你得到null,因此是一个异常,或者是一个盒装的非可空值,因此不是你想要的类型)。

(拳击是在这里弄乱你的断言 - 我认为IsType接受object。)

您可以使用类型推断来获取变量的类型作为类型参数:

public bool IsNullable<T>(T value)
{
    return Nullable.GetUnderlyingType(typeof(T)) != null;
}

当您在编译时知道确切的类型时,这并不是一个很大的用途,但是它对于泛型有用。 (当然,还有其他实现方法。)

你的现实生活情况如何?我认为这不是这样的断言,因为你在编译时就知道了这个断言。

答案 1 :(得分:3)

int? i = 0;
var type = TypedReference.GetTargetType(__makeref(i));
var isNullable = type.IsGenericType &&
    type.GetGenericTypeDefinition() == typeof(Nullable<>);

答案 2 :(得分:3)

我喜欢@ jon-skeet的答案,但它只有在你知道你正在测试的类型时才有效。在我们的世界中,我们使用反射打开对象并针对正则表达式测试值。

简化扩展以适用于任何类型的扩展工作。

public static bool IsNullable(this Type type)
{
    return Nullable.GetUnderlyingType(type) != null;
}
仿制药是生命的血液,但有时......:)

答案 3 :(得分:0)

Assert中的名称空间是什么?

以下按照您的预期返回true

int? wtf = 0;
if (typeof(Nullable<int>).IsInstanceOfType(wtf))
{
    // Do things
}

虽然值得注意的是typeof(Nullable<int>).IsInstanceOfType(42)也返回true - 这是因为此方法接受object,因此将其装箱为Nullable<int>

答案 4 :(得分:0)

这是我提出的,因为其他一切似乎都失败了 - 至少在可移植类库 / DotNet Core 上使用&gt; = C#6

基本上,您扩展泛型类型ObjectNullable<T>,并使用与基础类型匹配的静态扩展方法将被调用并优先于通用T扩展的事实-method。

public static partial class ObjectExtension
{
    public static bool IsNullable<T>(this T self)
    {
        return false;
    }
}

和一个Nullable<T>

public static partial class NullableExtension
{
    public static bool IsNullable<T>(this Nullable<T> self) where T : struct
    {
        return true;
    }
}

使用Reflection和type.IsGenerictype.GetGenericParameters()在我当前的.NET运行时集上不起作用。

答案 5 :(得分:0)

它对我有用,希望对你也有用。

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