c# - C# 中不可为空的只读引用和空的私有默认构造函数导致警告 CS8618
问题描述
我的一些 C# 类在设计上没有默认构造函数。我习惯于声明一个空的私有默认构造函数,以防止我的类的客户端使用编译器提供的默认构造函数。
现在我在我的 C# 项目 ( #nullable enable
) 中启用了不可为空的引用,这不再有效,我参考CS8618
下面的警告:
#nullable enable
public sealed class Operation
{
private readonly CancellationTokenSource _cts;
private Operation()
{
// Warning CS8618 Non-nullable field '_cts' is uninitialized.
// Consider declaring the field as nullable.
//_cts = null!;
}
public Operation(CancellationToken token)
{
_cts = CancellationTokenSource.CreateLinkedTokenSource(token);
}
...
}
看来,我现在要么必须初始化所有不可为空的字段(null!
我想是使用 null-forgiving 吗?),要么完全删除非默认构造函数。解决这个问题的优雅方法是什么?
更新以解决评论:
也许我不够清楚,所以我会尝试解决这个问题。我很清楚,public
如果我没有明确声明,C# 会提供一个默认的无参数构造函数。这正是我声明它并使其成为的原因private
。这可以防止Operation
使用无参数构造函数构造类型的对象。我还有一个工厂类:
public static class OperationFactory
{
public static Operation* CreateOperation(CancellationToken token)
{
return new Operation(token);
}
}
我班的客户可以:
var operation = new Operation(token)
或者
var operation = OperationFactory.CreateOperation(token)
但他们不允许这样做:
// this would create an object in invalid state
var operation = new Operation();
所以以前,为了强加这些规则,我只需要声明一个空的私有无参数构造函数:private Operation() {}
。
现在有了#nullable enable
,我不能再有一个空的私有构造函数。我现在必须在私有构造函数(它仍然从未使用过,所以这是一个缺点)和公共构造函数中初始化所有不可为空的引用字段。
因为私有构造函数基本上从未使用过,所以我认为可能有一种优雅的方法可以避免重复此类初始化代码。有没有?
解决方案
这里似乎对文档所述内容存在误解。
具体来说,文档指出:
如果你没有为你的类提供构造函数,C# 默认创建一个实例化对象并将成员变量设置为 C# 类型的默认值一文中列出的默认值的构造函数。
请注意,它没有说的是:
如果您不为您的类提供无参数构造函数,...
如果您声明任何构造函数,编译器将不会添加无参数的构造函数。
因此,您的类可以更改为此,只需删除私有无参数构造函数:
public sealed class Operation
{
private readonly CancellationTokenSource _cts;
public Operation(CancellationToken token)
{
_cts = CancellationTokenSource.CreateLinkedTokenSource(token);
}
...
}
由于您在那里有一个构造函数public Operation(CancellationToken token)
,因此编译器不会添加无参数构造函数,并且您将阻止任何人这样做:
new Operation()
另一方面,如果您自己的代码确实需要无参数构造函数,那么编译器是正确的。该_cts
字段将保留其默认值,即null
. 在这种情况下,您必须弄清楚如何处理它null
,并可能告诉编译器“您是对的,我会这样标记它”以消除警告。
推荐阅读
- openiddict - 使用客户端凭据作为用户管理器的一部分
- java - Hadoop 3.1.1 命令不提供输出 Mac OSX
- reactjs - 为什么我会收到“未能找到有效的摘要”错误?
- android - libc:pthread_create 失败:无法分配 1040384 字节堆栈:内存不足
- google-analytics - 什么是属性点击量?
- java - 使用 maven 和多个 git 存储库 - 减轻痛苦
- terraform - 如何引用导入的 terraform 资源
- javascript - 自动装卸元件
- python - 如何将对象类型映射到具有大型数据集的 pandas.DataFrame 中的 int64
- javascript - 如何检测OLED显示器?