【问题标题】:Compiler error of "Non-nullable field is uninitialized" even though it was initialized in InitializeComponents function“Non-nullable field is uninitialized”的编译器错误,即使它已在 InitializeComponents 函数中初始化
【发布时间】:2019-08-15 16:45:50
【问题描述】:

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

class SomeClass : Form {
  Button b;

  SomeClass() {
    InitializeComponents();
  }

  SomeClass(Container x) {
    InitializeComponents();
  }

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

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

当然我可以将 b 标记为可空(按钮?b),但是,现在我会在每次使用 b 时收到警告,因为未检查可空性(它不能为空...)

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

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

尤瓦尔

【问题讨论】:

    标签: c# winforms c#-8.0 nullable-reference-types


    【解决方案1】:

    根据preview docs

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

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

    因此,现在没有办法在不将该赋值直接移入构造函数(或在声明它的行上赋值)的情况下实现您想要的。

    【讨论】:

    • 因为您已经回答了这个问题,所以添加了一些属性,例如[MaybeNull]。您知道是否添加了任何内容来告诉编译器该字段始终被初始化?
    • 我不知道这样的事情@andre_ss6。
    【解决方案2】:

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

    class SomeClass : Form {
      private readonly Button b;
    
      public SomeClass() {
        b = new Button();
      }
    
      public SomeClass(Container x): this() {
        // Something else...
      }
    }
    

    不幸的是,这是一个众所周知的当前限制,此外,所有设计器生成的代码都不会遵循此模式,那么您可能需要在此处放置一些 #nullable disable(或其他指令之一,视情况而定)并在那里。

    【讨论】:

      猜你喜欢
      • 2021-09-27
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多