C# 10 新特性 —— 补充篇
C# 10 新特性 —— 補(bǔ)充篇
Intro
前面已經(jīng)寫了幾篇文章介紹 C# 10 新特性的文章,還有一些小的更新
Constant interpolated strings
在之前的版本中,如果想要使用插值字符串來(lái),則不能聲明為一個(gè)常量
如果依賴于一個(gè)常量的插值字符串就只能聲明為一個(gè) static 的變量,比如說(shuō)下面這個(gè)例子:
private?const?string?Name?=?"Alice"; private?static?readonly?string?Hello?=?$"Hello?{Name}";在 C# 10 中我們可以將 Hello 也聲明為常量(const),如下:
public?string?const?Name?=?"Alice"; public?string?const?Hello?=?$"Hello?{Name}";這種常量插值字符串參數(shù)只適用于字符串,如果是 int 就不行了,比如說(shuō),如果寫一段下面這樣的代碼:
private?const?int?Num?=?10; private?const?string?HelloNum?=?$"Hello?{Num}";這里插值字符串的參數(shù)是一個(gè) int 類型,實(shí)際編譯器會(huì)直接報(bào)錯(cuò),報(bào)錯(cuò)信息如下:
// Error ? CS0133 ?The expression being assigned to 'ConstantInterpolatedStringSample.HelloNum' must be constant
上一篇文章中,我們有提到像 int/DateTime 等這種數(shù)據(jù)字符串插值是會(huì)依賴當(dāng)前的一個(gè) CultureInfo,所以作為插值字符串的時(shí)候不是一個(gè)編譯時(shí)就確定的一個(gè)值,不能被認(rèn)為是常量
這個(gè)特性的插值參數(shù)必須是字符串常量。
Extended property patterns
C# 10 針對(duì)模式匹配有一點(diǎn)小優(yōu)化,針對(duì)嵌套的屬性模式寫法做了一些簡(jiǎn)化,如:
if?(e?is?MethodCallExpression?{?Method:?{?Name:?"MethodName"?}?})C# 10 新寫法:
if?(e?is?MethodCallExpression?{?Method.Name:?"MethodName"?})一個(gè)完整的簡(jiǎn)單小例子如下:
record?TestModelA(TestModelB?B,?string?Name); record?TestModelB(TestModelC?C,?string?Name); record?TestModelC(string?Name);var?a?=?new?TestModelA(new?TestModelB(new?TestModelC("C"),?"B"),?"A"); if?(a?is?{?B.C.Name.Length:?>?0?}) {Console.WriteLine(a.B.C.Name); }Record types can seal ToString
在 C# 10 中我們可以把 record 類型的 ToString() 方法標(biāo)記為 sealed,這樣繼承于它的子類就不能再重寫這個(gè)方法了,可以用來(lái)保護(hù) ToString() 輸出的格式,保證輸出的格式是一致的,使用起也很簡(jiǎn)單,直接在 ToString 方法中聲明 sealed 即可,示例如下:
record?Person(string?Name,?int?Age) {public?sealed?override?string?ToString(){return?Name;} }這樣如果繼承于它的 record 想要重寫 ToString 方法的時(shí)候就會(huì)報(bào)錯(cuò)
前面我們提到過(guò) C# 10 中增加了 record struct,它可以使用這個(gè)特性嗎?答案是不可以,這一特性僅針對(duì)于 record class,在 record struct 中使用會(huì)得到一個(gè)類似下面的錯(cuò)誤
Assignment and declaration in same deconstruction
在之前的版本中,我們?nèi)绻胍褂?tuple 返回值,必須要同時(shí)初始化,如下:
private?static?(int?month,?int?day)?GetDate() {var?today?=?DateTime.Today;return?(today.Month,?today.Day); }(var?month,?var?day)?=?GetDate(); Console.WriteLine($"Month:?{month},?day:?{day}");我們必須要同時(shí)聲明 month/day,在 C# 10 中我們既可以使用已有變量又可以聲明新的變量,可以結(jié)合在一起使用,如下:
(var?month,?var?day)?=?GetDate(); Console.WriteLine($"Month:?{month},?day:?{day}");(month,?var?day2)?=?GetDate(); Console.WriteLine($"Month:?{month},?day:?{day2}");(month,?day)?=?GetDate(); Console.WriteLine($"Month:?{month},?day:?{day}");Improved definite assignment
C# 10 中編譯器會(huì)做更多的推斷從而大大方便我們的使用,之前介紹的 Lamdba 的一些優(yōu)化都是由編譯器做的推斷,針對(duì)于初始化賦值的 null 檢查也有一些優(yōu)化,下面是微軟給出的一個(gè)示例,在之前的版本中會(huì)有警告,但是在 C# 10 之后就沒(méi)有警告了
string?representation?=?"N/A"; if?((c?!=?null?&&?c.GetDependentValue(out?object?obj))?==?true) {representation?=?obj.ToString();?//?undesired?error }//?Or,?using??. if?(c?.GetDependentValue(out?object?obj)?==?true) {representation?=?obj.ToString();?//?undesired?error }//?Or,?using??? if?(c?.GetDependentValue(out?object?obj)????false) {representation?=?obj.ToString();?//?undesired?error }Allow AsyncMethodBuilder attribute on methods
從 C# 10 開(kāi)始我們可以在異步方法上設(shè)置 AsyncMethodBuild 來(lái)自定義要處理異步任務(wù)的方式,這有對(duì)于要實(shí)現(xiàn)性能更好的異步方法處理方式的用戶會(huì)更加的方便
比如這樣一個(gè)異步方法:
public?async?ValueTask<T>?ExampleAsync()?{?...?}實(shí)際編譯器會(huì)生成這樣的代碼:
[AsyncStateMachine(typeof(<ExampleAsync>d__29))] [CompilerGenerated] static?ValueTask<int>?ExampleAsync() {<ExampleAsync>d__29?stateMachine;stateMachine.<>t__builder?=?AsyncValueTaskMethodBuilder<int>.Create();stateMachine.<>1__state?=?-1;stateMachine.<>t__builder.Start(ref?stateMachine);return?stateMachine.<>t__builder.Task; }使用這種方式,我們可以控制異步方法的處理
[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))]?//?new?usage,?referring?to?some?custom?builder?type static?async?ValueTask<int>?ExampleAsync()?{?...?}這樣實(shí)際生成的代碼類似下面這樣
[AsyncStateMachine(typeof(<ExampleAsync>d__29))] [CompilerGenerated] [AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))]?//?retained?but?not?necessary?anymore static?ValueTask<int>?ExampleAsync() {<ExampleAsync>d__29?stateMachine;stateMachine.<>t__builder?=?PoolingAsyncValueTaskMethodBuilder<int>.Create();?//?<>t__builder?now?a?different?typestateMachine.<>1__state?=?-1;stateMachine.<>t__builder.Start(ref?stateMachine);return?stateMachine.<>t__builder.Task; }更多細(xì)節(jié)可以參考:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/async-method-builders
Generic Attribute
Generic Attribute 目前還不算是 C# 10 新特性中的一部分,但是已經(jīng)可以使用了,需要聲明 LangVersion 為 preview,否則會(huì)看到類似下面的一個(gè)錯(cuò)誤
Generic Attribute Requires preview LangVersion因?yàn)榭梢杂昧?#xff0c;而且想在我的項(xiàng)目里使用,所以想嘗試一下,但是就目前來(lái)說(shuō),還不能滿足我的需要,簡(jiǎn)單看一下好了
我們可以這樣用
[ExcelConfiguration<TestModel>] public?class?TestModel {public?int?Id?{?get;?set;?}public?string?Title?{?get;?set;?}?=?string.Empty; }[AttributeUsage(AttributeTargets.Class?|?AttributeTargets.Struct)] public?class?ExcelConfigurationAttribute<T>?:?Attribute {public?string?DefaultFileName?{?get;?set;?}?=?"unnamed-file.xlsx";public?Func<T,?bool>?DataValiadator?{?get;?set;?}?=?_?=>?true; }但是如果想在聲明 Attribute 的地方指定泛型委托會(huì)報(bào)錯(cuò),錯(cuò)誤信息如下:
'DataValiadator' is not a valid named attribute argument because it is not a valid attribute parameter type
Generic Lambda Error類似的還有一個(gè) Generic Math 的功能也可以預(yù)覽使用,但是對(duì)我來(lái)說(shuō)感覺(jué)意義不是特別大,所以就不介紹了,感興趣的可以參考:https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/
對(duì)于預(yù)覽版特性,如果不是特別需要建議還是不要輕易在生產(chǎn)代碼里用,以后被砍了就尷尬了
More
原來(lái)有很多原本計(jì)劃在 C#10 的特性被推到了 C# 11中,比如 filed 關(guān)鍵詞、required 成員針對(duì)集合的模式匹配等,但總體來(lái)說(shuō)還是有很多不錯(cuò)的新特性了,還沒(méi)用 C# 10 的小伙伴們可以用起來(lái)了~~
C# 10 新特性解析的系列文章到此就結(jié)束了,如果有錯(cuò)誤的地方歡迎指出,萬(wàn)分感謝
C# 10 新特性的示例代碼可以從 Github 上獲取:https://github.com/WeihanLi/SamplesInPractice/tree/master/CSharp10Sample
更多特性介紹可以參考微軟的文檔,可以參考文末的參考鏈接
References
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/constant_interpolated_strings
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/extended-property-patterns
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/improved-definite-assignment
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/async-method-builders
總結(jié)
以上是生活随笔為你收集整理的C# 10 新特性 —— 补充篇的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: WPF 实现温度计
- 下一篇: 打独立运行包遇到无法trim咋解决