Не допускающие значения NULL ссылки только для чтения и пустой частный конструктор по умолчанию в C# приводят к предупреждению CS8618 - PullRequest
0 голосов
/ 10 июля 2020

Некоторые из моих C# классов не имеют конструктора по умолчанию по умолчанию. Я привык объявлять пустой частный конструктор по умолчанию, чтобы запретить клиентам моего класса использовать предоставленный компилятором конструктор по умолчанию.

Теперь я включил ссылки, не допускающие значения NULL, в моем проекте 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! , Я полагаю?) Или вообще удалить нестандартный конструктор. Каков элегантный способ решить эту проблему?

Обновите, чтобы учесть комментарии:

Может быть, я недостаточно ясно понял, поэтому я постараюсь это исправить. Мне хорошо известно, что C# предоставляет public конструктор без параметров по умолчанию, если я не объявляю его явно. Именно поэтому я его объявляю и делаю 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 у меня больше не может быть частного конструктора empty . Теперь мне нужно инициализировать все мои ссылочные поля, не допускающие значения NULL, как в частном конструкторе (который до сих пор никогда не используется, поэтому это недостаток), так и в конструкторе publi c.

Поскольку частный конструктор является по сути, никогда не использовался, я подумал, что есть элегантный способ избежать дублирования такого кода инициализации. Есть ли?

1 Ответ

1 голос
/ 10 июля 2020

Кажется, здесь возникло недопонимание относительно того, что говорится в документации.

В частности, в документации указано:

Если вы не предоставляете конструктор для вашего класса, 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, и, вероятно, сказать компилятору: «Вы правы, я отмечу это как таковое», чтобы подавить предупреждение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...