Почему я не получаю предупреждение, не допускающее значения NULL (или какое-либо другое предупреждение), если FieldTwo не задано в конструкторе? Я использую .Net 5.0, и для параметра Nullable в файле проекта установлено значение true.

  public class MyClass
  {
    public string FieldOne;
    public long FieldTwo;

    public MyClass (string p1, long p2)
    {
      FieldOne = p1;
      // FieldTwo is not set. Where is the non-nullable warning!?
    }
  }

2
cdimitroulas 15 Сен 2021 в 12:35

2 ответа

Лучший ответ

long является типом значения и не может быть пустым. Таким образом, нет причин предупреждать о нуле. Я подозреваю, что вам нужно предупреждение о том, что поле не инициализировано.

Если частное поле никогда не назначается, возникает предупреждение CS0649. Однако, если поле общедоступное или изменено где-либо в классе, это предупреждение не возникает. Например, следующий код будет вполне приемлемым и не должен выдавать предупреждения:

public class MyClass{
    private long myLong;
    public void Increment() => myLong++;
}

Если поле должно быть установлено только из конструктора, вы должны объявить его как доступное только для чтения. Однако общедоступные поля только для чтения не вызывают предупреждения, даже если они, вероятно, должны. См. Почему я НЕ получаю предупреждения о неинициализированных полях только для чтения?.

2
JonasH 15 Сен 2021 в 11:03

long является типом значения и не может быть пустым. Типы значений всегда инициализируются при объявлении значения по умолчанию, в данном случае 0. Вам придется изменить тип поля на long?, если вы хотите сохранить null

В любом случае эти поля не являются свойствами. Это не просто семантика. Поля - это детали реализации, даже общедоступные. Они не считаются частью поверхности API класса. Свойства являются частью API, они сериализуются по умолчанию всеми сериализаторами (поля этого не делают) и гарантируют, что наличие общедоступных полей - это запах кода.

Чтобы гарантировать, что все свойства инициализированы, вы можете использовать тип record вместо class:

public record(string PropertyOne, long PropertyTwo);

Это создает класс со свойствами, доступными только для инициализации, для PropertyOne и PropertyTwo и конструктор, который требует значений для всех свойств. Наряду с операторами равенства, деконструкторами и реализацией ToString(), которая возвращает все свойства в форме строки JSON.

1
Panagiotis Kanavos 15 Сен 2021 в 10:11