“Non-nullable field is uninitialized”的编译器错误,即使它已在 InitializeComponents 函数中初始化
Posted
技术标签:
【中文标题】“Non-nullable field is uninitialized”的编译器错误,即使它已在 InitializeComponents 函数中初始化【英文标题】:Compiler error of "Non-nullable field is uninitialized" even though it was initialized in InitializeComponents function 【发布时间】: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 中非常常见的模式(每个组件...)
尤瓦尔
【问题讨论】:
【参考方案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
(或其他指令之一,视情况而定)并在那里。
【讨论】:
以上是关于“Non-nullable field is uninitialized”的编译器错误,即使它已在 InitializeComponents 函数中初始化的主要内容,如果未能解决你的问题,请参考以下文章