Ошибка компилятора «Поле, не обнуляемое, не инициализировано», даже если оно было инициализировано в функции InitializeComponents - PullRequest
0 голосов
/ 25 марта 2019

В WinForms распространено, что общая функция инициализации инициализирует ссылочные переменные (например)

class SomeClass : Form {
  Button b;

  SomeClass() {
    InitializeComponents();
  }

  SomeClass(Container x) {
    InitializeComponents();
  }

  void InitializeComponents() {
    b = new Button();
  }
}

Как видите, b всегда инициализируется ненулевым значением. Тем не менее, C # 8 по-прежнему будет жаловаться, что SomeClass () не инициализирует ненулевое значение b.

Конечно, я мог пометить b как nullable (кнопка? B), однако теперь я получу предупреждение при каждом использовании b, так как nullability не проверяется (он не может быть нулевым ...)

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

Обратите внимание, что это очень распространенный шаблон в WinForms (каждый компонент ...)

Юваль

Ответы [ 2 ]

3 голосов
/ 25 марта 2019

Согласно документам предварительного просмотра :

Q: Почему выдается предупреждение о полях, которые инициализируются не напрямую конструктором или вне конструктора?

A: Компилятор распознает поля, назначенные явно только в текущем конструкторе, и предупреждает о других полях, объявленных как необнуляемые.Это игнорирует другие способы, которыми поля могут быть инициализированы, такие как фабричные методы, вспомогательные методы, установщики свойств и инициализаторы объектов.Мы будем исследовать распознавание общих шаблонов инициализации, чтобы избежать ненужных предупреждений.

Итак, прямо сейчас достичь того, что вы хотите, не перемещая это назначение непосредственно в конструктор (или присваивая его в строке, которая объявляет это).

2 голосов
/ 25 марта 2019

Для вашего очень конкретного примера решение состоит в том, чтобы объединить InitializeComponent() в конструктор по умолчанию и вызвать его из второго.

class SomeClass : Form {
  private readonly Button b;

  public SomeClass() {
    b = new Button();
  }

  public SomeClass(Container x): this() {
    // Something else...
  }
}

К сожалению, это общеизвестное текущее ограничение, и, более того, весь код, сгенерированный дизайнером, не будет следовать этому шаблону, тогда вам может потребоваться поместить здесь #nullable disable (или одну из других директив, в зависимости от ситуации) и есть.

...