即使在InitializeComponents函数中初始化了“非空字段未初始化”的编译器错误

时间:2019-03-25 12:32:58

标签: c# winforms c#-8.0 nullablereferencetypes

在WinForms中,常见的初始化函数是初始化参考变量(例如)

class SomeClass : Form {
  Button b;

  SomeClass() {
    InitializeComponents();
  }

  SomeClass(Container x) {
    InitializeComponents();
  }

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

如您所见,b始终被初始化为非null值。但是,C#8仍然会抱怨SomeClass()不会初始化不可为空的值b。

我当然可以将b标记为可为空(按钮?b),但是,由于未检查可为空性(它不能为null ...),因此现在我将对b的每次使用发出警告。

解决此问题的最佳方法是什么。是否有一个属性可用于将InitializeComponent标记为始终由构造方法调用?

请注意,这是WinForms(每个组件...)中非常常见的模式

Yuval

3 个答案:

答案 0 :(得分:3)

按照assign

  问:为什么对已初始化的字段报告警告?   是由构造函数间接地还是在构造函数外部?

     

A:编译器识别当前字段中明确分配的字段   仅构造函数,并警告声明为不可为空的其他字段。   这忽略了字段初始化的其他方式,例如工厂   方法,辅助方法,属性设置器和对象初始化器。我们   将调查识别常见的初始化模式以避免   不必要的警告。

因此,现在无法实现您想要的目标,而无需将该分配直接移到构造函数中(或在声明它的行上分配它)。

答案 1 :(得分:2)

对于您的非常具体的示例,解决方案是将InitializeComponent()合并到默认构造函数中,并从第二个构造函数中调用它。

class SomeClass : Form {
  private readonly Button b;

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

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

不幸的是,这是众所周知的当前限制,而且,所有设计人员生成的代码都不会遵循这种模式,因此您可能需要放置一些#nullable disable(或其他适当的一条指令)在这里和那里。

答案 2 :(得分:-1)

设为私有字段: 私人System.Windows.Forms.Button button1;