如何告知编译器调用基类方法后Input属性不为null?
解决CS8602警告:告知编译器基类方法调用后Input非空
问题场景
基类代码:
public MyClass? Input { get; set; } protected virtual void DoSomething() { Input = new(); }
子类重写DoSomething方法时,尝试修改Input的属性:
protected override void DoSomething() { base.DoSomething(); Input.Name = "Test"; }
此时收到编译器警告:
CS8602 - Dereference of a possibly null reference.
虽然可以用Input!.Name强制消除警告,但不想每次都使用空原谅运算符,希望有更优雅的方式告知编译器:调用基类DoSomething后Input必然非空。
解决方案
方案1:修改基类,使用MemberNotNull特性(推荐,若能修改基类)
在基类的DoSomething方法上添加[MemberNotNull]特性,明确告知编译器:调用该方法后Input成员不为null。
需要先引入System.Diagnostics.CodeAnalysis命名空间:
using System.Diagnostics.CodeAnalysis; public MyClass? Input { get; set; } [MemberNotNull(nameof(Input))] protected virtual void DoSomething() { Input = new(); }
修改后,子类重写时直接访问Input.Name就不会再触发警告,编译器能正确推断Input的非空状态。
方案2:子类中添加非空检查(无法修改基类时使用)
如果不能修改基类,可以在子类的DoSomething方法中添加非空检查,既消除编译器警告,还能增加运行时安全性:
protected override void DoSomething() { base.DoSomething(); ArgumentNullException.ThrowIfNull(Input); Input.Name = "Test"; }
ArgumentNullException.ThrowIfNull会在Input为null时抛出异常,同时编译器能识别这个检查,推断后续Input非空。
方案3:使用局部变量接收并确保非空
也可以用局部变量接收Input,并通过空合并运算符强制确保非空:
protected override void DoSomething() { base.DoSomething(); var input = Input ?? throw new InvalidOperationException("Input未被基类方法初始化"); input.Name = "Test"; }
这种方式同样能让编译器推断局部变量input非空,同时在运行时验证基类方法的行为符合预期。
内容的提问来源于stack exchange,提问作者Marvin Klein
相关产品推荐
相关产品推荐

