Обязательное свойство init с резервным полем выдает нулевое предупреждение C# 11

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

Приведенный ниже код выдает предупреждение:

Предупреждение CS8618 Ненулевое поле '_name' должно содержать ненулевое значение при выходе из конструктора. Рассмотрите возможность объявления поля как обнуляемого.

      public class TestRequiredInit
{
    private readonly string _name;

    public required string Name
    {
        get => _name;
        init => _name = value;
    }
}

Я не вижу способа создатьTestRequiredInitбез_nameустанавливается в ненулевое значение.

Это ошибка в MSBuild/VS или я что-то упустил?

Обновите, чтобы люди не рекомендовали использование автоматического свойства

Я немного упростил приведенный выше код, чтобы задать вопрос. Я хочу иметь возможность добавить логику инициализации в инициализатор свойства.

      public class TestRequiredInit
{
    private readonly string _name;

    public required string Name
    {
        get => _name;
        init
        {
            if (value.Length > 50)
            {
                throw new ArgumentException();
            }

            _name = value;
        }
    }
}

1 ответ

Между свойствами и их резервными полями нет формальной связи (если они вообще есть, что не требуется), поэтому допустимость значения NULL по необходимости анализируется отдельно от . Более того, хотя сеттеры считаются частью этапа построения (поэтому им разрешено делать такие вещи, как инициализация других свойств), они формально не являются частью построения для целей анализа допустимости значений NULL — что было правильно до введения , так как не было необходимости звонить им.

Анализ допустимости значений NULL можно расширить, чтобы специально рассматривать установщики свойств как часть конструкции для целей анализа, поэтомусчитается, что сеттер ушелв известном ненулевом состоянии, но получение этого права не является тривиальным — например, поскольку мы не можем предположить какой-либо порядок, в котором вызываются методы установки, мы должны предполагать внутри каждого метода установки, что поля могут быть, если конструктор не t определенно назначать их не нулевыми, поэтому мы можем дать соответствующие предупреждения. Это инверсия текущей семантики, когда установщикам разрешено предполагать, что поля не, так как в настоящее время они могут полагаться на конструктор, сделавший это, с учетом существующих предупреждений. Становится еще круче, если сеттеримущество не являетсяsetter, так как он может быть вызван как во время, так и после построения — должны ли мы всегда предупреждать, просто чтобы быть в безопасности?

Все это, и я даже не рассматривал, как это взаимодействует с производными классами. Я бы определенно сказал: «Это можно считать ошибкой, но формальное определение желаемой семантики и ее реализация с минимальным количеством сюрпризов — это довольно большая работа, которая еще не была проделана».

Другие вопросы по тегам