如何解决C#:泛型 T 的默认值?不为空;通用约束的行为改变
我有一个泛型类应该对(不可为空的)引用和值类型(参数、返回...)进行操作,但内部需要可以为空的字段。
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?");
}
}
在启用可空值的情况下编译 (.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? 表示 Nullable<T>
,因此如果您使用 Gen<int>.Write("int?")
,字段 t
将是 Nullable<int>
。但是 Gen<string>.Write("string")
根本不会编译,因为 string
不是 struct
。所以和约束有完全不同的意义。
启用 C#8 后,您可以删除 struct
约束,然后 t
仍然是 int
,而 string
将是可空的 string
。所以问号的意思是:在引用类型的情况下,它是一个可以为空的引用类型,否则它就是这样。
在不使用所需泛型类型的情况下,您不能同时拥有既可以是可为空引用类型的泛型类型,也可以是可为空值类型的泛型类型,因此如果它必须可以为空,请使用 int?
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。