我有一个泛型类,应该对(不可为空)引用和值类型(参数、返回...)进行操作,但内部需要可以为空的字段。
using System;
public class Gen<T> // where T : struct
{
public class Data
{
public T? t;
}
public static void Write(string s)
{
Data d = new Data();
Console.WriteLine("Default of {0} is {1}", s, d.t == null ? "null" : "NOT null");
}
// ... other stuff that uses T and not T? like
// public T DoSomething(T value) ...
}
static class Program
{
static void Main(string[] args)
{
Gen<int>.Write("int?");
Gen<string>.Write("string?");
}
}
在启用可为 null 的情况下编译 (.NET 5) 时,此代码不会产生任何错误或警告。
然而,行为并不符合我的预期。
Default of int? is NOT null
Default of string? is null
在寻找解决方案时,我发现当where T : struct
添加约束(并删除 Gen.Write()),行为更改为
Default of int? is null
奇怪的是,约束改变了行为。
有人知道编写这样一个通用类的优雅解决方案吗?
使用也支持引用类型的自定义 Nullable 类或为每个 T 使用单独的 bool 标志?归档有点乏味。
如果你想使用Nullable<int>
你不应该使用int
,所以使用:
Gen<int?>.Write("int?");
那么输出将是
Default of int? is null
Default of string? is null
问题中的代码是一个示例。真正的类没有Write
方法并且从不使用该类型的字符串。然而正如我
由“其他内容”表示,它使用 T 以及 T?。所以它不是
想要实例化它int?
代替int
.
首先我想解释一下为什么这并不奇怪struct
泛型类中的约束会改变行为。因为实际上,如果您是 T? means Nullable<T>
,所以如果你使用Gen<int>.Write("int?")
场t
将是一个Nullable<int>
。但是之后Gen<string>.Write("string")
根本不会编译string
不是一个struct
。所以它与约束有着完全不同的含义。
启用 C#8 后,您可以删除struct
受约束,那么t
仍然是int
和string
将是一个可为空的string
。所以问号的含义是:对于引用类型,它是可为空的引用类型,否则它就是这样。
您不能同时拥有可以为 null 的引用类型的泛型类型或可以为 null 的值类型而不使用所需的泛型类型,因此请使用int?
如果它必须可为空。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)