通过reflection检测可空类型

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

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

所以只是出于好奇,你如何确定给定的实例是否是Nullable 对象?

首先, Nullable是一个结构,所以没有这样的对象 。 你不能调用GetType() ,因为它会将值设置为空(此时你要么得到null,因此得到一个exception,或者一个盒装的非可空值,因此不是你想要的类型)。

(拳击是在这里弄乱你的断言 – 我会假设IsType接受object 。)

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

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

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

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

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

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

简化任何类型的扩展工作对我们来说更好。

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

仿制药是生命的血液但有时候…… 🙂

Assert名称空间是什么?

以下返回true如您所愿:

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

虽然值得注意的是typeof(Nullable).IsInstanceOfType(42)也返回true – 这是因为此方法接受一个object ,因此被装箱为Nullable

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

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

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

和一个Nullable

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

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