如何识别泛型类型的可为空的引用类型? [英] How to identify a nullable reference type for generic type?
问题描述
在启用了可为空的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 $ c时允许值无例外$ c>是可为空的,例如
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屋!