2021年4月19日微軟釋出公告稱將於今年夏季釋出首款64位的 Visual Studio 2022,2021年5月20日又釋出了 Visual Studio 2022 線路圖,進一步提升開發生產力。與 Visual Studio 黃金搭檔的 C# 語言一直都是秒天秒地秒空氣的存在。C#10,今天它來了。
小小的免責宣告,這些變化大多數幾乎都完成了。由於它仍在積極開發中,我不能保證一切都與 C# 10 釋出時完全一樣。
他首先談到的是 record 的當前實現是使用類(reference type)作為基物件的。C#10中即將提供一個 record struct,它的基礎型別可以是值型別。不同之處在於,常規 record 將通過引用從一個函式傳遞到另一個函式,而 record struct 將通過其值進行復制。record struct 也將支援 with 表示式。
同時,還可以向 record 中新增運算子。這兩種 record 型別都可以使用。
record Person(string Name, string Email) { public static Person operator +(Person first, Person second) { // TODO 業務邏輯 } }
C# 團隊關注的目標之一是使物件的初始化更容易。這就是為什麼可以根據需要對 class
,struct
,record
或 record struct
新增 required 特性標記
。它強制要求這些屬性必須賦值。這可以通過建構函式來完成,或者可以通過物件初始化來完成。下面的兩個類定義是等效的。如果用required
關鍵字寫的話,不設定Name
屬性就不能例項化Person 。編譯器會丟擲錯誤並且無法編譯。
class Person { public required string Name { get; set; } public DateTime DateOfBirth { get; set; } } class Person { public Person(string name) => Name = name; public string Name { get; set; } public DateTime DateOfBirth { get; set; } }
為了進一步改善屬性(properties),可以完全擺脫 backing field。新的關鍵字 field 將提供對所述支援欄位的訪問。它對 setter 和 init only 屬性都可以使用。
class Person { public string Name { get; init => field = value.Trim(); } public DateTime DateOfBirth { get; set => field = value.Date; } }
在下一個版本中也會有一些漂亮的小改進。其中之一就是 with
操作符也將支援匿名型別。
var foo = new { Name = "Foo", Email = "foo@mail.com" }; var bar = foo with {Name = "Bar"};
現在可以建立一個檔案,其中的名稱空間匯入可以在任何地方使用。例如,如果在幾乎每個檔案中都使用了一個常用的名稱空間,例如Microsoft.Extensions.Logging.ILogger,那麼就可以將全域性名稱空間 using Microsoft.Extensions.Logging.ILogger 新增到任何.cs檔案中(我建議使用Program.cs或專用Imports.cs),整個專案中都可以使用 logger 介面。但是,該方法不適用於整個解決方案(solution)。因為沒有人能預測哪些地方需要匯入,所以它們是按專案分組到每個專案(project)中。
隨後,還會對 namespace
進行優化。現在 namespace
需要花括號 {} 來對程式碼進行分組,這意味著所有程式碼至少要縮排一次。為了節省 tab(或四個空格)和螢幕空間,在檔案中的任何位置新增一個 namespace,將使所有程式碼都屬於該namespace
。有相關研究表明絕大多數情況下,一個檔案中的幾乎所有程式碼都屬於同一個 namespace
。使用該方案優化後,檔案大小會減小,這對於一個解決方案(即使它包含數千個檔案)來說可能並不重要,但在 GitHub/GitLab/BitBucket/...的規模上,我認為這將為他們節省一些空間。如果有人仍想在一個檔案中包含多個名稱空間,則仍然可以選擇使用大括號。
// 傳統方式 LegacyNamespace.cs namespace LegacyNamespace { class Foo { // ToDo 業務邏輯 } } // 簡化後的方式 SimplifiedNamespace.cs namespace SimplifiedNamespace; class Bar { // ToDo 業務邏輯 }
lambda 語句也有一些很酷的更新。編譯器將更好地支援推斷 lambda 簽名,並且還可以新增屬性。可以指定顯式返回型別以幫助編譯器理解 lambda。
var f = Console.WriteLine; var f = x => x; // 推斷返回型別 var f = (string x) => x; // 推斷簽名 var f = [NotNull] x => x; // 在屬性上新增特性 var f = [NotNull] (int x) => x; var f = [return: NotNull] static x => x; // 為返回型別新增特性 var f = T () => default; // 顯示返回型別 var f = ref int (ref int x) => ref x; // 在 struct 上使用 ref 關鍵字 var f = int (x) => x; // 顯式指定隱式輸入的返回型別 var f = static void (_) => Console.Write("Help");
最後,可以在介面上指定靜態方法和屬性。我知道這將是一個有爭議的話題,就像向介面新增預設實現一樣。雖然我不喜歡它,然而這可能非常有趣。想象一下,您可以指定介面的預設值或指定建立方法。
interface IFoo { static IFoo Empty { get; } static operator +(IFoo first, IFoo second); }
class Foo : IFoo { public static IFoo Empty => new Foo(); public static operator +(IFoo first, IFoo second) => /* 在此做邏輯計算 */; }
就個人而言,我喜歡這些變化。尤其是 namespace 和 interface 的
變化和改進。不管怎樣,C#的未來是光明的。
參考文獻:
- https://kenbonny.net/introducing-csharp-10