2026年11月13日 星期五

[AI 分享] C# 15 新功能:聯合型別、封閉類別與更靈活的語法

[AI 分享] C# 15 新功能:聯合型別、封閉類別與更靈活的語法

摘要 : C# 15 加入聯合型別、封閉類別等功能,強化型別安全並簡化程式碼。



內容:


這場分享由 C# 團隊成員接續主題演講,透過程式範例介紹 C# 15 的新功能。講者表示,聯合型別是團隊討論多年的設計,如今終於能用簡潔的語法,表達「一個值只能是指定幾種型別之一」。


**聯合型別(union)**的示範從寵物資料開始:程式需要同時處理狗、貓和鳥,但這些型別可能來自不同程式庫,並非開發者自行建立的繼承階層。過去若以 object 儲存,任何物件都能混入,連不希望出現的鯊魚也不例外;對 object 撰寫 switch 運算式時,編譯器也無法確認所有可能情況都已處理。


C# 15 可以宣告「Pet 是由 Dog、Cat、Bird 組成的 union」。這些成員稱為 case types。宣告後,三種指定型別都能隱含轉換為 Pet,未列入的 Shark 則會產生編譯錯誤。程式也能直接針對各 case type 進行模式比對;當三種情況都已處理,編譯器便能確認比對具有窮盡性,不再要求額外處理未知物件。


如果其中一個 case type 允許 null,編譯器會明確提醒尚未處理 null。補上對應分支後,窮盡性警告就會消失。講者強調,這類具體的編譯器回饋,能引導開發者逐步補齊必要情況。


Union 本身是真正的型別宣告,不只能使用簡短的分號形式,也能加入大括號、泛型參數及屬性或方法等功能成員。例如,可以把處理不同寵物的邏輯寫成 Pet 的輔助屬性。不過,這種 union 不允許另外宣告儲存狀態:其中的值就是它的狀態。


講者也展示編譯器預設如何實作 union。預設產生的是 struct,包含保存目前值的 Value 屬性,以及接收各 case type 的建構函式;隱含轉換可藉由呼叫相應建構函式完成,模式比對則會取出值來判斷。編譯器產生的型別也會實作 IUnion,方便程式在不知道具體 union 型別時,仍能辨識 union 並取得其值。


開發者亦可自行建立 union:在類別或結構上標示 Union attribute,提供必要的值屬性與建立成員,讓編譯器辨識其 case types。這對效能要求較高,或想讓既有型別具備 union 行為的情境特別有用。例如,預設實作以較寬泛的型別儲存值,可能使實值型別發生裝箱;自行實作便能選擇其他儲存與取值方式。


第二項重點是 closed 類別。講者以計算機的運算型別為例:程式定義數字、加、減、乘、除等衍生類別,並用模式比對遞迴計算。但只要公開的基底類別仍可由外部繼承,其他專案就可能加入新的衍生型別,編譯器也無法保證現有比對已涵蓋全部情況。


將基底類別宣告為 closed 後,只有同一組件內的型別能直接繼承它;其他組件的繼承宣告會成為編譯錯誤。closed 也使該類別自動具有抽象類別的性質。如此一來,開發者可以保留既有的繼承模型,同時讓編譯器確認模式比對是否窮盡,而不必為了改用 union 重整整個資料結構。


第三項功能擴充了集合運算式。集合運算式原本適合簡潔地建立集合,但若建立時需要傳入參數,例如替 HashSet 指定忽略大小寫的比較器,或替 List 指定初始容量,過去往往得改回明確呼叫建構函式。C# 15 允許在方括號開頭使用 with 並提供參數,讓程式在保留集合運算式寫法的同時,控制集合的建立方式。


第四項是帶標籤的 break 與 continue。在巢狀迴圈中,若內層條件成立便要跳出外層迴圈,過去可能需要額外的布林變數,再於外層檢查。現在可以替目標迴圈加上標籤,直接指定要跳離或繼續哪一層迴圈。講者指出,這能減少輔助狀態,讓控制流程更直接,也較不容易在修改程式時出錯。


第五項是擴充索引子(extension indexers)。C# 14 已讓擴充成員不再侷限於方法,例如可加入擴充屬性;C# 15 則進一步支援索引子。在擴充成員的宣告區塊中,開發者能沿用一般索引子的宣告語法。講者認為,這也顯示新的擴充成員設計可以自然延伸至更多成員種類。


分享最後提到另一項仍在預覽階段的功能:改進 unsafe 的標記與追蹤方式。其目標是讓開發者除了內建的不安全操作,也能標示自己撰寫的不安全操作,並在程式碼中的呼叫關係上持續追蹤,使這些操作更容易被辨識與檢查。此外,啟用相關改進後,async 程式碼也能因執行階段的支援而變得更快;它的用法沒有改變,重點在於效能提升。

沒有留言:

張貼留言