日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C# 10 新特性 —— CallerArgumentExpression

發布時間:2023/12/4 C# 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C# 10 新特性 —— CallerArgumentExpression 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C# 10 新特性 —— CallerArgumentExpression

Intro

C# 10 支持使用 CallerArgumentExpression 來自動地獲取調用方的信息,這可以簡化我們現在的一些代碼,讓代碼更加簡潔,一起看下面的示例吧

Caller Info

C# 在 5.0 的時候開始支持 Caller Info 自動獲取調用方的一些信息,C# 5 開始支持的 Caller Info Attribute 有三個,

  • [CallerMemberName] - 調用方成員名稱,方法名或者屬性名.

  • [CallerFilePath] - 調用方源代碼所在文件路徑

  • [CallerLineNumber] - 調用方所在源代碼的行數信息

在方法參數中添加一個 Attribute 來獲取調用方信息,使用示例如下:

public?static?void?MainTest() {//?我是誰,我在哪兒DumpCallerInfo(); }private?static?void?DumpCallerInfo([CallerFilePath]?string??callerFilePath?=?null,[CallerLineNumber]?int??callerLineNumber?=?null,[CallerMemberName]?string??callerMemberName?=?null ) {Console.WriteLine("Caller?info:");Console.WriteLine($@"CallerFilePath:?{callerFilePath} CallerLineNumber:?{callerLineNumber} CallerMemberName:?{callerMemberName} "); }

針對 CallerLineNumber 的類型是 int,所以參數類型需要能夠直接接收 int,如上面的 [CallerLineNumber] int? callerLineNumber = null 也可以改成 [CallerLineNumber] int callerLineNumber = -1 或者 [CallerLineNumber] long callerLineNumber = -1

但是不能改成 [CallerLineNumber] string callerLineNumber = null 或者 [CallerLineNumber] short callerLineNumber = -1

string 類型不兼容,short 不能隱式轉換

上面代碼輸出結果類似下面:

Caller?info: CallerFilePath:?C:\projects\sources\SamplesInPractice\CSharp10Sample\CallerInfo.cs CallerLineNumber:?8 CallerMemberName:?MainTest

CallerArgumentExpression

CallerArgumentExpression 也是屬于一種 Caller Info

下面這里是利用 CallerArgumentExpression 實現的幾個驗證方法,如果參數不合法就拋出一個異常,通過 CallerArgumenExpression 來自動的獲取調用方的參數表達式

public?static?class?Verify {public?static?void?Argument(bool?condition,?string?message,?[CallerArgumentExpression("condition")]?string??conditionExpression?=?null){if?(!condition)?throw?new?ArgumentException(message:?message,?paramName:?conditionExpression);}public?static?void?NotNullOrEmpty(string?argument,?[CallerArgumentExpression("argument")]?string??argumentExpression?=?null){if?(string.IsNullOrEmpty(argument)){throw?new?ArgumentException("Can?not?be?null?or?empty",?argumentExpression);}}public?static?void?InRange(int?argument,?int?low,?int?high,[CallerArgumentExpression("argument")]?string??argumentExpression?=?null,[CallerArgumentExpression("low")]?string??lowExpression?=?null,[CallerArgumentExpression("high")]?string??highExpression?=?null){if?(argument?<?low){throw?new?ArgumentOutOfRangeException(paramName:?argumentExpression,message:?$"{argumentExpression}?({argument})?cannot?be?less?than?{lowExpression}?({low}).");}if?(argument?>?high){throw?new?ArgumentOutOfRangeException(paramName:?argumentExpression,message:?$"{argumentExpression}?({argument})?cannot?be?greater?than?{highExpression}?({high}).");}}public?static?void?NotNull<T>(T??argument,?[CallerArgumentExpression("argument")]?string??argumentExpression?=?null)where?T?:?class{ArgumentNullException.ThrowIfNull(argument,?argumentExpression);} }

來看一個使用調用示例:

var?name?=?string.Empty; InvokeHelper.TryInvoke(()?=>?Verify.NotNullOrEmpty(name));

上面的 InvokeHelper.TryInvoke 是封裝的一個方法,如果有異常會記錄一個日志

上面代碼執行結果如下:

可以看到我們的名稱也是被記錄了下來 Parameter 名字就是我們傳入的變量名,不需要我們再手動的額外加一個 nameof(name) 了

再來看一個調用示例,調用代碼如下:

var?num?=?10; InvokeHelper.TryInvoke(()?=>?Verify.InRange(num,?2,?5)); InvokeHelper.TryInvoke(()?=>?Verify.InRange(num,?10?+?2,?10?+?5));

輸出結果如下:

如果沒有變量名或者屬性名等,就會直接用傳入進來的 value 字面量,如果傳入進來的是一個表達式,那么記錄下來的就是表達式本身,比如上面輸出的 5/10 + 2,而 num 是傳入的一個變量,就會獲取到變量的名字,是不是很神奇,很多驗證的地方就可以簡化很多了

Sample

CallerArgumentExpression 有一個很典型的一個實際應用就是 .NET 6 里新增的一個 API

ArgumentNullException.ThrowIfNull() 方法,這個方法的實現如下:

///?<summary>Throws?an?<see?cref="ArgumentNullException"/>?if?<paramref?name="argument"/>?is?null.</summary> ///?<param?name="argument">The?reference?type?argument?to?validate?as?non-null.</param> ///?<param?name="paramName">The?name?of?the?parameter?with?which?<paramref?name="argument"/>?corresponds.</param> public?static?void?ThrowIfNull([NotNull]?object??argument,?[CallerArgumentExpression("argument")]?string??paramName?=?null) {if?(argument?is?null){Throw(paramName);} }[DoesNotReturn] private?static?void?Throw(string??paramName)?=>throw?new?ArgumentNullException(paramName);

源碼可以從 Github 上看 https://github.com/dotnet/runtime/blob/v6.0.0/src/libraries/System.Private.CoreLib/src/System/ArgumentNullException.cs

我們實際調用的時候就可以不傳參數名,會自動的獲取參數名,示例如下:

object??xiaoMing?=?null; InvokeHelper.TryInvoke(()?=>?ArgumentNullException.ThrowIfNull(xiaoMing));

輸出結果如下:

從上面的結果我們可以看到,參數名已經自動的解析出來了

More

升級 .NET 6 的小伙伴快用這個改造你的代碼吧,然后就是很多 null 檢查也可以使用新的 ArgumentNullException.ThrowIfNull 去簡化代碼吧~~

想使用上述代碼測試,可以從 Github 獲取 https://github.com/WeihanLi/SamplesInPractice/blob/master/CSharp10Sample/CallerInfo.cs

References

  • https://www.codeproject.com/Tips/606379/Caller-Info-Attributes-in-Csharp-5-0

  • https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/caller-argument-expression?WT.mc_id=DT-MVP-5004222

  • https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/caller-information?WT.mc_id=DT-MVP-5004222

  • https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10?WT.mc_id=DT-MVP-5004222#callerargumentexpression-attribute-diagnostics

  • https://github.com/dotnet/runtime/blob/v6.0.0/src/libraries/System.Private.CoreLib/src/System/ArgumentNullException.cs

  • https://github.com/WeihanLi/SamplesInPractice/blob/master/CSharp10Sample/CallerInfo.cs

總結

以上是生活随笔為你收集整理的C# 10 新特性 —— CallerArgumentExpression的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。