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#的未來是光明的。
參考文獻: