承上文 在 C# 中 Nullable Reference Types 使用属性MemberNotNull
我们继续探讨...
使用属性 MemberNotNullWhen
假设一个例子
class Person{ static readonly Regex _nameReg = new Regex(@"^I'm \w*"); private string _name; public Person(string name) { if (!TryInitialize(name)) _name = "invalid name"; } private bool TryInitialize(string name) { if (_nameReg.IsMatch(name)) { _name = name; return true; } else return false; }}
这段程式码定义了一个类别 Person
,在这个类别中有一个正规表达式物件_nameReg
定义成唯读与静态属性,它是用来匹配名字是否符合特定格式。
类别中还有一个私有字串属性 _name
和一个建构子方法 public Person(string name)
,建构子方法中有一个判断式,如果呼叫 TryInitialize
方法传回的值是 false
,就将 _name
属性初始化为字串 "invalid name"
。
类别中还有一个私有方法 private bool TryInitialize(string name)
,它会使用 _nameReg
属性来匹配传入的名字字串,如果匹配成功就将 _name
属性初始化为传入的名字,并传回布林值。
接着,编译器将对上面的程式码发出警告:
警告讯息如下:
警告CS8618退出建构函式时,不可为 Null 的 栏位 '_name' 必须包含非 Null 值。请考虑将 栏位 宣告为可为 Null。
按照警告提示他希望你在变数或参数型别前面加上 ?,来表示这个型别可以是空值。例如private string? _name;
但在这个实作中,明明在建构子中将会为 _name
属性赋值,所以它不可能在建构子结束时为空值。
要解决这种情况,您可以使用属性MemberNotNullWhen:
[MemberNotNullWhen(true, nameof(_name))]private bool TryInitialize(string name)
MemberNotNullWhen 属性是 C# 8.0 中新引入的可空性侦错工具,
它可以让你在执行阶段确保特定条件下,某个成员不会是空值。
加入后 编译器的警告 就消失了
如果你尝试对 _name
属性进行存取,但是它是空值,则会抛出 NullReferenceException 例外。
这个属性可以让你在程式码中清楚地表达你的意图,并让程式在执行阶段更稳定。
了解更多:MemberNotNullWhenAttribute Class