C# 11 中的参数 null 检查
C# 11 中的參數 null 檢查
Intro
C# 11 將引入一個新的操作符 !! 來簡化我們代碼中的對于參數的 null 檢查,昨天發布的 .NET 7 Preview 1 已經支持了這一語法,感興趣的不妨來試一下吧,下面我們就來看一下如何使用吧
Prepare
如果你想在本地代碼中進行編譯測試,需要安裝 .NET 7 Preview 1 的 SDK,下載地址:
然后在本地創建一個控制臺應用程序,可以通過命令?dotnet new console 來創建
創建成功之后,手動修改項目文件,配置 C# 語言版本為 preview,如下所示添加 <LangVersion>preview</LangVersion>:
<Project?Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net7.0</TargetFramework>????<ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable> +???<LangVersion>preview</LangVersion></PropertyGroup></Project>Sample
!! 是一個新的操作符,加在參數后面編譯器會自動生成一段 null 檢查的代碼
bang-bang operator
下面我們就來試一下吧,測試代碼如下:
Hello("World");try {Hello(null!); } catch?(Exception?ex) {Console.WriteLine(ex); }void?Hello(string?name!!) {Console.WriteLine($"Hello,?{name}!"); }運行 dotnet run 來執行代碼,可以看到類似下面的輸出結果:
output可以看到當傳了一個 null 的時候,會拋出一個 ArgumentNullException 的異常,說明確實是做了 null 檢查的
這個操作符不僅僅適用于方法參數,也可以用于委托參數、索引器等
What's inside
從上面的輸出結果我們可以看到有做 null 檢查,實際是什么樣子的呢?我們可以反編譯一下代碼來看一下實際生成的代碼是怎么樣的
反編譯的結果如下:
Program 類型和 Main 方法 是由編譯器自動生成的,這是 C# 9 引入的頂級語句 (Top-Level Statements)
可以看到我們代碼中的 Hello 方法沒有了,有一個編譯器生成的另外一個方法,它是我們原來方法的變形,只增加了一句代碼
<PrivateImplementationDetails>.ThrowIfNull(name,?"name");我們再看一下其中的實現,實現如下:
PrivateImplementationDetails可以看到在這里實現了 null 檢查,如果參數是 null 就會拋出 ArgumentNullException 異常
看到這里相信大家都知道是怎么實現的了,那么有個問題可以思考一下,這里我們使用了一個方法,如果有兩個這樣的方法會是什么樣的呢?<PrivateImplementationDetails> 這個類會生成兩個嗎?我們來嘗試一下,我們把這個方法拷貝一下改個名字再來反編譯一下
void?Hello1(string?name!!)?=>?Console.WriteLine($"Hello,?{name}!");反編譯結果如下:
可以看到實際是調用的同一個方法,<PrivateImplementationDetails> 這個類型只生成了一次
那如果這兩個方法是在兩個項目中會怎么樣呢?可以自己動手試一下~~
More
這個操作符使用時,還有一些注意事項
如果你啟用了可空引用類型,并將參數聲明為可空的引用類型,編譯器會產生一個警告,因為實際上是不應該為 null 的,為 null 就會拋異常,所以編譯器會警告,示例如下:
//?warning?CS8995:?Nullable?type?'string?'?is?null-checked?and?will?throw?if?null. //?void?Hello2(string??name!!)?=>?Console.WriteLine($"Hello,?{name}!");值類型是不能使用這個操作符的,因為值類型是不會為 null 的,編譯器會直接報錯,但可空值類型是可以的,例如:
//?error?CS8992:?Parameter?'int'?is?a?non-nullable?value?type?and?cannot?be?null-checked. //?void?Hello3(int?name!!)?=>?Console.WriteLine($"Hello,?{name}!");另外 out 參數也不能使用這個操作符,如:
//?error?CS8994:?'out'?parameter?'name'?cannot?be?null-checked. //?void?Hello4(out?string?name!!)?=>?name?=?"World";想要嘗試的小伙伴可以裝一下 .NET 7 preview 1 來體驗,如果不想裝 preview 也可以通過 一個在線網站 sharplab https://sharplab.io/ 來體驗編譯器的新特性
.NET runtime 中的代碼已經用上了這個新的操作符來簡化參數的 null 檢查,可以參考:https://github.com/dotnet/runtime/pull/64720
References
https://github.com/dotnet/csharplang/blob/c7361547c0c00e0116f6e4ac3767d7b6bc7442b6/proposals/param-nullchecking.md
https://github.com/dotnet/runtime/pull/64720
https://github.com/WeihanLi/SamplesInPractice/tree/master/CSharp11Sample
總結
以上是生活随笔為你收集整理的C# 11 中的参数 null 检查的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ABP vNext微服务架构详细教程——
- 下一篇: CentOS单机安装k8s并部署.NET