繁体   English   中英

通过反射检测可空类型

[英]Detecting a Nullable Type via reflection

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

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

因此,出于好奇,您如何确定给定实例是否为 Nullable<> object?

首先, Nullable<T>是一个结构体,所以没有这样的对象 您不能调用GetType() ,因为这会装箱该值(此时您要么获得 null 从而导致异常,要么获得装箱的不可为空值,因此不是您想要的类型)。

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

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

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

当您在编译时知道您的示例中的确切类型时,这并不是大量使用,但它对泛型很有用。 (当然,还有其他实现方式。)

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

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

简化适用于任何类型的扩展对我们来说效果更好。

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

仿制药是生命的血液,但有时... :)

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

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

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

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;
    }
}

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

Assert在什么命名空间中?

如您所料,以下返回true

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

尽管值得注意的是typeof(Nullable<int>).IsInstanceOfType(42)也返回 true - 这是因为此方法接受一个object ,因此被装箱为Nullable<int>

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

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

基于弗拉基米尔的回答

public static class GenericExtensions
{
   public static bool IsNullable<T>(this T item) =>
     TypedReference.GetTargetType(__makeref(item)).FullName.Contains("System.Nullable");
}

用法:

int? nullableInt = 42;
bool nIntIsNullable = nullableInt.IsNullable();

持续时间:平均机器<2ms。

评论:

这对我有用,可以检查类型是否为 Nullable..

type.Assembly.FullName.StartsWith("System") && type.Name.Contains("Nullable");

只有这种方式适用于我使用 .net core 7 的情况

bool isNullable = propertyInfo.GetMethod is null ? false : new NullabilityInfoContext().Create(propertyInfo.GetMethod.ReturnParameter).ReadState == NullabilityState.Nullable;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM