通过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
也返回true – 这是因为此方法接受一个object
,因此被装箱为Nullable
。
这是我提出的,因为其他一切似乎都失败了 – 至少在可移植类库 / DotNet Core上> = C#6
基本上,您扩展了generics类型Object
和Nullable
并使用了与基础类型匹配的静态扩展方法将被调用并优先于通用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.IsGeneric
和type.GetGenericParameters()
在我当前的.NET运行时集上不起作用。