通过反射检测可空类型

发布于 2024-11-07 20:15:44 字数 157 浏览 0 评论 0原文

令人惊讶的是,以下代码断言失败:

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

出于好奇,如何确定给定实例是否为 Nullable<>反对与否?

Surprisingly the following code fails the 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

守护在此方 2024-11-14 20:15:45

首先,Nullable 是一个结构体,因此不存在这样的对象。您不能调用 GetType(),因为这会将值装箱(此时您要么得到 null,从而出现异常,要么得到装箱的不可空值,因此不是您想要的类型) 。

(装箱是这里搞乱你的断言的原因 - 我假设 IsType 接受 object。)

不过,你可以使用类型推断来获取 变量的类型< /em> 作为类型参数:

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

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

您的现实生活情况是什么?我认为这不是这样的断言,因为您在编译时就知道这个断言的答案。

Well firstly, Nullable<T> is a struct, so there isn't an object as such. 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).

(Boxing is what's messing up your assertion here - I would assume that IsType accepts 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.

后来的我们 2024-11-14 20:15:45

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

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

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

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

I like the @jon-skeet answer but it only works if you know the type you are testing against. 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... :)

能否归途做我良人 2024-11-14 20:15:45
int? i = 0;
var type = TypedReference.GetTargetType(__makeref(i));
var isNullable = type.IsGenericType &&
    type.GetGenericTypeDefinition() == typeof(Nullable<>);
int? i = 0;
var type = TypedReference.GetTargetType(__makeref(i));
var isNullable = type.IsGenericType &&
    type.GetGenericTypeDefinition() == typeof(Nullable<>);
¢好甜 2024-11-14 20:15:45

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

MyClass mclass = new MyClass();    

PropertyInfo[] properties = mclass.GetType().GetProperties();

foreach (PropertyInfo propertyInfo in properties)
{
   bool nullable = propertyInfo.GetMethod is null ? false : new NullabilityInfoContext().Create(propertyInfo.GetMethod.ReturnParameter).ReadState == NullabilityState.Nullable;
   if (nullable)
      {
        //some script to do
      }
}

Only this way worked in my case using .net core 7

MyClass mclass = new MyClass();    

PropertyInfo[] properties = mclass.GetType().GetProperties();

foreach (PropertyInfo propertyInfo in properties)
{
   bool nullable = propertyInfo.GetMethod is null ? false : new NullabilityInfoContext().Create(propertyInfo.GetMethod.ReturnParameter).ReadState == NullabilityState.Nullable;
   if (nullable)
      {
        //some script to do
      }
}
作业与我同在 2024-11-14 20:15:45

Assert 位于哪个命名空间?

正如您所期望的,以下内容返回 true

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

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

What namespace is Assert in?

The following returns true as you would expect:

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>.

埋葬我深情 2024-11-14 20:15:45

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

基本上你扩展了通用类型 < code>Object 和 Nullable 并使用以下事实:将调用与基础类型匹配的静态扩展方法,并优先于泛型 T 扩展方法。

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

一个用于 Nullable

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

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

Here is what I came up with, as everything else seemed to fail - at least on Portable Class Library / 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.

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

and one for 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.

梦过后 2024-11-14 20:15:45

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

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

It works fo me, hope for you too.

public static bool IsNullable(this Type type)
{
    return Nullable.GetUnderlyingType(type) != null;
}
勿挽旧人 2024-11-14 20:15:45

基于 Vladimir 答案

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();

持续时间:平均机器上 <2 毫秒。

备注:

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.

Remarks:

始终不够爱げ你 2024-11-14 20:15:45

这对我来说可以检查类型是否可为空。

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

This works for me to check wether a type is Nullable or not..

type.Assembly.FullName.StartsWith("System") && type.Name.Contains("Nullable");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文