如何识别泛型类型的可为空的引用类型? [英] How to identify a nullable reference type for generic type?

查看:312
本文介绍了如何识别泛型类型的可为空的引用类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在启用了可为空的C#8中,是否有一种方法可以为泛型类型标识为可为空的引用类型

In C# 8 with nullable enabled, is there a way to identify a nullable reference type for generic type?

对于可为空的值类型,其中有专门的部分。
https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/builtin-types/nullable-value-types#how-to-identify- a-nullable-value-type

For nullable value type, there is a section dedicated to it. https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types#how-to-identify-a-nullable-value-type

我们正在尝试根据通用类型进行可选的空检查

We are trying to do optional null check according to the generic type

#nullable enable
public static Result<T> Create<T>(T value)
{
   if (!typeof(T).IsNullable() && value is null)
      throw new ArgumentNullException(nameof(value));

   // Do something
}

public static bool IsNullable(this Type type)
{
   // If type is SomeClass, return false
   // If type is SomeClass?, return true
   // If type is SomeEnum, return false
   // If type is SomeEnum?, return true
   // If type is string, return false
   // If type is string?, return true
   // If type is int, return false
   // If type is int?, return true
   // etc
}

因此以下内容将抛出 ArgumentNullException T 不可为空时
但在 T 是可为空的,例如

So the following will throw ArgumentNullException when T is not nullable But allow value to be null with no exception when T is nullable, e.g.

Create<Anything>(null); // throw ArgumentNullException

Create<Anything?>(null); // No excception


推荐答案


在启用了nullable的C#8中,是否有一种方法可以为通用类型标识 nullable
引用类型

C#8 中,无法检查传递给泛型方法的类型参数是否为可为空的引用类型。

In C# 8 there is NO way to check if a type parameter passed to a generic method is a nullable reference type or not.

问题在于,任何可为空的引用类型 T?都由同一类型表示T 但带有与由实际.NET类型 Nullable<表示的可空值类型 T?相反T>

The problem is that any nullable reference type T? is represented by the same type T (but with a compiler-generated attribute annotating it), as opposed to nullable value type T? that is represented by the actual .NET type Nullable<T>.

当编译器生成调用通用方法 F< T> 的代码时,其中 T 可以是可为空的引用类型,不能为如果 T 为可空引用类型,则丢失。让我们考虑下一个示例方法:

When compiler generates code that invokes a generic method F<T>, where T can be either nullable reference type or not, an information if T is nullable refence type is lost. Lets consider the next sample method:

public void F<T>(T value) { }

对于下一次调用

F<string>("123");
F<string?>("456");

编译器将生成下一个 IL 代码(我将其简化为位):

compiler will generate the next IL code (I simplified it a bit):

call    F<string>("123")
call    F<string>("456")

您可以看到,第二种方法的类型参数 string 是传递而不是 string?,因为在执行过程中可为空的引用类型 string?的表示形式与 string

You can see that to the second method a type parameter string is passed instead of string? because the representation of the nullable reference type string? during the execution is the same type string.

因此,执行期间无法定义传递给泛型方法的类型参数是否可为空

我认为对于您的情况,最佳解决方案是通过 bool 值,该值指示引用类型是否可为空。这是一个示例,说明如何实现:

I think that for your case an optimal solution would be to pass a bool value that will indicate if a reference type is nullable or not. Here is a sample, how it can be implemented:

public static Result<T> Create<T>(T value, bool isNullable = false)
{
    Type t = typeof(T);

    // If type "T" is a value type then we can check if it is nullable or not.
    if (t.IsValueType) 
    {
        if (Nullable.GetUnderlyingType(t) == null && value == null)
            throw new ArgumentNullException(nameof(value));
    }
    // If type "T" is a reference type then we cannot check if it is nullable or not.
    // In this case we rely on the value of the argument "isNullable".
    else
    {
        if (!isNullable && value == null)
            throw new ArgumentNullException(nameof(value));
    }

    ...
}

这篇关于如何识别泛型类型的可为空的引用类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆