首页 > 解决方案 > 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# 默认创建一个实例化对象并将成员变量设置为 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,并可能告诉编译器“您是对的,我会这样标记它”以消除警告。


推荐阅读