C# 13 即 .Net 9 按照計劃會在2024年11月發佈,目前一些新特性已經定型,今天讓我們來預覽一個比較大型比較重要的新特性: 擴展類型 extension types ...
C# 13 即 .Net 9 按照計劃會在2024年11月發佈,目前一些新特性已經定型,今天讓我們來預覽一個比較大型比較重要的新特性:
擴展類型 Extension types
在5月份的微軟 Build 大會中的 What’s new in C# 13 會議上,兩位大佬花了很長的篇幅來演示這個特性。
這個特性一直是大家很關心的,在 github 的 issue 上討論的也是如火如荼,當然微軟也鴿了好多年:(
首先,讓我們來回顧一下 C# 中的擴展方法
using System;
var zhangsan = new Person();
Console.WriteLine(zhangsan.GetAge());
public class Person
{
public string Name { get; set; }
public DateTime Birthday { get; set; }
}
public static class PersonExtension
{
public static int GetAge(this Person person) => DateTime.Now.Year - person.Birthday.Year;
}
以上代碼演示了一個擴展方法聲明方式及使用方法。
我們在不侵入 Person 類的基礎上為 Person 類擴展了一個 GetAge() 的方法,雖然已經可以很方便的擴展出一些方法來,但是問題也是顯而易見的,例如必須聲明在靜態類中、語法看起來很怪異、只能擴展方法而不能擴展屬性等等。
於是,在即將到來的 C# 13 中,我們可以這樣
var zhangsan = new Person();
Console.WriteLine(zhangsan.GetAge());
public implicit extension PersonExtension for Person
{
public int GetAge() => DateTime.Now.Year - this.Birthday.Year;
}
怎麼樣,語義是不是清晰了很多?
進一步的,年齡應該是一個屬性而不應該是一個方法
var zhangsan = new Person();
Console.WriteLine(zhangsan.Age);
public implicit extension PersonExtension for Person
{
public int Age => DateTime.Now.Year - this.Birthday.Year;
}
困擾多年的如何擴展屬性的問題終於得到瞭解決。
implicit extension / explicit extension
在上一個例子,不知道大家有沒有註意到關鍵字是 implicit extension,那麼很顯然,會有一個對應的 explicit extension,下麵讓我們來看看花活
var zhangsan = new Person();
if(zhangsan.IsStudent)
{
Student zhangsanAsStudent = zhangsan;
Console.WriteLine(zhangsanAsStudent.Grade);
}
public implicit extension PersonExtension for Person
{
public int Age => DateTime.Now.Year - this.Birthday.Year;
public bool IsStudent => this.Age < 18;
}
public explicit extension Student for Person
{
public string Grade => "五年級";
}
可以看到,這裡有一個顯示擴展,顯式擴展可以創建原始類的投影或子類。當你要基於擴展類型添加條件方法或屬性時,這可能很有用。
當然,擴展靜態方法也是沒問題的
var zhangsan = Person.Create();
public implicit extension PersonExtension for Person
{
public static Person Create() => new Person();
}
當然,系統類型也是支持的
Console.WriteLine("World".SayHello());
public implicit extension StringExtension for string
{
public string SayHello() => "Hello" + this;
}
結尾
我想這個特性是很大的一個改變,或許可以改進 C# 代碼的組織方式,有望提高代碼的可讀性、可維護性和表現力。通過允許開發人員在不修改原始代碼的情況下向現有類添加功能,它可以促進代碼重用並減少修改原始類的需要。
另外據瞭解,這個特性以及相關特性,例如擴展介面等等,並不會在 C# 13 (.Net 9) 中完整的放出來,而是會在後續版本中逐漸解鎖。
參考
https://build.microsoft.com/en-US/sessions/689e5104-72e9-4d02-bb52-77676d1ec5bc?source=sessions
https://devblogs.microsoft.com/dotnet/dotnet-build-2024-announcements/
https://github.com/dotnet/csharplang/issues/5497