简体   繁体   English

通过反射检测可空类型

[英]Detecting a Nullable Type via reflection

Surprisingly the following code fails the Assert:令人惊讶的是,以下代码未能通过 Assert:

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

So just out curiosity, how can you determine if a given instance is a Nullable<> object or not?因此,出于好奇,您如何确定给定实例是否为 Nullable<> object?

Well firstly, Nullable<T> is a struct, so there isn't an object as such.首先, Nullable<T>是一个结构体,所以没有这样的对象 You can't call GetType() , as that will box the value (at which point you either get null and thus an exception, or a boxed non-nullable value and therefore not the type you want).您不能调用GetType() ,因为这会装箱该值(此时您要么获得 null 从而导致异常,要么获得装箱的不可为空值,因此不是您想要的类型)。

(Boxing is what's messing up your assertion here - I would assume that IsType accepts object .) (拳击在这里弄乱了你的断言 - 我假设IsType接受object 。)

You can use type inference though to get the type of the variable as a type parameter:您可以使用类型推断来获取变量的类型作为类型参数:

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

That's not a huge amount of use when you know the exact type at compile-time as in your example, but it's useful for generics.当您在编译时知道您的示例中的确切类型时,这并不是大量使用,但它对泛型很有用。 (There are alternative ways of implementing it, of course.) (当然,还有其他实现方式。)

What's your real life situation?你的现实生活是怎样的? I assume it's not an assertion like this, given that you know the answer to this one at compile time.我认为这不是这样的断言,因为您在编译时就知道了这个断言。

I like the @jon-skeet answer but it only works if you know the type you are testing against.我喜欢@jon-skeet 的答案,但它只有在您知道要测试的类型时才有效。 In our world we are using reflection to open up objects and test values against regex expressions.在我们的世界中,我们使用反射来打开对​​象并针对正则表达式测试值。

simplifying the extension to work for any type worked better for us.简化适用于任何类型的扩展对我们来说效果更好。

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

generics are life's blood but sometimes... :)仿制药是生命的血液,但有时... :)

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

Here is what I came up with, as everything else seemed to fail - at least on Portable Class Library / DotNet Core with >= C# 6这是我想出的,因为其他一切似乎都失败了 - 至少在可移植类库/ DotNet Core with >= C# 6

Basically you extend generic Type Object and Nullable<T> and use the fact that the static extension method that matches the underlying type is going to be invoked and takes precedence over the generic T extension-method.基本上,您扩展泛型 Type ObjectNullable<T>并使用与基础类型匹配的静态扩展方法将被调用并优先于泛型T扩展方法的事实。

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

and one for Nullable<T>一个用于Nullable<T>

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

Using Reflection and type.IsGeneric and type.GetGenericParameters() did not work on my current set of .NET Runtimes.使用反射和type.IsGenerictype.GetGenericParameters()在我当前的 .NET 运行时集上不起作用。

What namespace is Assert in? Assert在什么命名空间中?

The following returns true as you would expect:如您所料,以下返回true

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

Although its worth noting that typeof(Nullable<int>).IsInstanceOfType(42) also returns true - this is because this method accepts an object and so gets boxed as a Nullable<int> .尽管值得注意的是typeof(Nullable<int>).IsInstanceOfType(42)也返回 true - 这是因为此方法接受一个object ,因此被装箱为Nullable<int>

It works fo me, hope for you too.它对我有用,也希望对你有用。

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

Based on Vladimir answer :基于弗拉基米尔的回答

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

Usage:用法:

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

Duration: <2ms on average machine.持续时间:平均机器<2ms。

Remarks:评论:

This works for me to check wether a type is Nullable or not..这对我有用,可以检查类型是否为 Nullable..

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

Only this way worked in my case using .net core 7只有这种方式适用于我使用 .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