C# 9.0 新特性预览 - 空参数校验
<h1 id="c-90-新特性预览---空参数校验">C# 9.0 新特性预览 - 空参数校验</h1><p><br>
</p>
<h3 id="前言">前言</h3>
<p>随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它们。<br><br>
</p>
<h3 id="目录">目录</h3>
<p><br><br><br><br><br><br></p>
<p></p>
<h3 id="简便的空参数校验-simplified-null-argument-checking">简便的空参数校验 (Simplified Null Argument Checking)</h3>
<p></p>
<h4 id="目的">目的</h4>
<p>这个特性主要是为了更简便的检查方法的参数是否为 null 并抛出 ArgumentNullExceptiony 异常。<br>
</p>
<h4 id="语法">语法</h4>
<p>语法很简单,在参数名后加个叹号即可:</p>
<pre><code class="language-csharp">void M(string name!) {
...
}
</code></pre>
<p>以上代码会被翻译为:</p>
<pre><code class="language-csharp">void M(string name) {
if (name is null) {
throw new ArgumentNullException(nameof(name));
}
...
}
</code></pre>
<p>想必有些同学已经从上面代码看出来了,这个生成的空校验,只是校验参数是否为 null,这也就意味着它无法在值类型上使用,以下代码将报错:</p>
<pre><code class="language-csharp">// Error: 无法在值类型参数上使用!操作符
void G<T>(T arg!) where T : struct {
}
</code></pre>
<p>当然,可空的值类型是可以的,但是编译器会提示一条警告,提示你在可空类型上进行了空检查:</p>
<pre><code class="language-csharp">// Warning: 将显式null检查与可为null的类型结合使用
void M(int? x!) {
}
</code></pre>
<p>类似的,在参数拥有默认值的情况下,也会提示警告</p>
<pre><code class="language-csharp">// Warning: 参数 'x' 进行了空检查但是它默认为空
void M(string x! = null) {
}
</code></pre>
<p></p>
<h4 id="构造方法的场景">构造方法的场景</h4>
<p>在构造方法的场景下,空参数校验将发生在任何其他代码的前面,包括:</p>
<ul>
<li>对其他构造方法的链式调用,即 this() 或 base()</li>
<li>在构造方法内的隐式字段初始化</li>
</ul>
<p>举个例子:</p>
<pre><code class="language-csharp">class C {
string field = GetString();
C(string name!): this(name) {
...
}
}
</code></pre>
<p>以上代码会大致翻译为以下伪代码:</p>
<pre><code class="language-csharp">class C {
C(string name)
if (name is null) {
throw new ArgumentNullException(nameof(name));
}
field = GetString();
:this(name);
...
}
</code></pre>
<p></p>
<h4 id="lambda-的场景">Lambda 的场景</h4>
<p>这个特性在 lambda 中也可以使用</p>
<pre><code class="language-csharp">void G() {
Func<string, string> s = x! => x;
}
</code></pre>
<p></p>
<h4 id="不可以使用的场景">不可以使用的场景</h4>
<p>这个特性只能用于有方法体的方法中,也就意味着它不能用于抽象方法、接口、委托和部分方法。<br>以下代码编译器会报错:</p>
<pre><code class="language-csharp">interface C
{
public int M(string x!);// ERROR
}
</code></pre>
<p>不能用于属性。因为属性 setter 中的 value 是隐式的,不会出现在参数列表中,所以此特性不适用于属性。</p>
<pre><code class="language-csharp">string FirstName! { get; set; } // ERROR
</code></pre>
<p>不能用于 out / ref / in 的参数</p>
<pre><code class="language-csharp">public void M(out string x!) {} // ERROR
</code></pre>
<p></p>
<h3 id="参考">参考</h3>
<p><br><br></p><br><br>
来源:https://www.cnblogs.com/Rwing/p/csharp-9-0-preview-null-arg-checking.html
頁:
[1]