如何解决C#中属性与成员的空引用警告问题?
解决C# null引用警告的正确方式
问题分析
你的代码出现的警告根源在于编译器对字段初始化状态的追踪逻辑:
- 当给
SomeModel属性添加[MemberNotNull(nameof(_someModel))]时,编译器认为**整个属性(包括getter)**需要保证_someModel非空,但getter仅返回字段、无赋值逻辑,因此触发CS8774和CS8603警告。 - 移除该属性后,编译器无法通过属性setter的调用追踪到
_someModel已被初始化,因此触发CS8618警告,认为不可空字段未在构造函数中赋值。
正确解决方式
方式一:将[MemberNotNull]标注在属性setter上
只有setter操作会确保_someModel变为非空,因此将特性仅标注在setter上,让编译器明确知道setter执行后字段非空:
private SomeFormModel _someModel; public SomeFormModel SomeModel { get => _someModel; [MemberNotNull(nameof(_someModel))] set { _someModel = value; _someModel.Subview = true; } } public CurrentFormModel() { SomeModel = new(); }
方式二:直接初始化字段或构造函数赋值
让编译器直接识别字段已完成初始化,无需依赖属性setter的追踪:
子方式2a:字段声明时初始化
private SomeFormModel _someModel = new(); public SomeFormModel SomeModel { get => _someModel; set { _someModel = value; _someModel.Subview = true; } } public CurrentFormModel() { _someModel.Subview = true; }
子方式2b:构造函数直接给字段赋值
private SomeFormModel _someModel; public SomeFormModel SomeModel { get => _someModel; set { _someModel = value; _someModel.Subview = true; } } public CurrentFormModel() { _someModel = new(); _someModel.Subview = true; }
方式三:使用null原谅运算符(不推荐)
通过!强制告诉编译器字段非空,这种方式属于抑制警告,不如前两种方式严谨,仅在确定字段不可能为null时使用:
private SomeFormModel _someModel; public SomeFormModel SomeModel { get => _someModel!; set { _someModel = value; _someModel.Subview = true; } } public CurrentFormModel() { SomeModel = new(); }
推荐方案
优先选择方式一或方式二,这两种方式能让编译器准确追踪字段状态,避免潜在的null引用风险,同时消除警告。
内容的提问来源于stack exchange,提问作者puzzler
相关产品推荐
相关产品推荐

