在C#6和VB 12中不可變對象(Immutable Objects )更易用
英文原文:Easier Immutable Objects in C# 6 and VB 12
.NET 編程中的一個痛點: 為了實現不可變對象 (Immutable Objects ),需要編寫大量樣板代碼。 不可變類(immutable class)不同于一個普通的類,它要求每個屬性具有一個單獨定義的字段,當然,還需要通過一個構造函數來填充每個字段的填。
根據新的規范草案,C#和 VB 將增加一個稱為“記錄類”(record class)的特性。實質上, 它是僅由在構造函數中定義的不可變類 (immutable class)。
下面是規范的一行代碼示例:
public record class Cartesian (double x: X, double y: Y);
除了這個構造函數外,編譯器會自動創建:
- 生成每個參數的只讀屬性(read-only property)
- 生成 Equals 函數
- 重寫 GetHashCode 函數
- 重寫 ToString 函數
- 生成一個“is”操作符,在 VB 中稱為“Matches”
“is/Matches”操作符被用于模式匹配 (pattern matching),我們會在未來的文章涉及到。除此之外,記錄類(record classes)和C#匿名類型(anonymous types)很相近(和 VB 的匿名類型有所不同,它們默認是可變的)。對這兩種概念,微軟正研究如何協調,尤其是基于現有的程序集中,還不能對外暴露匿名類型接口。
不可變類型的一個通用特性是在對對象的一個或多個字段進行改變后,會自動產生當前對象的拷貝。雖然在規范中沒有提到,但微軟正在考慮為C#提供如下方式作為一種選項:
var x1 = new MyRecord (1, 2, 3);var x2 = x1 with B: 16; Console.WriteLine (x2) // prints something like "A = 1, B = 16, C = 3"
擴展記錄類
你可能已經注意到,在 Cartesian 示例類中,用分號表示結束。表明該類不包含任何類體,只保留由編譯器負責自動生成提供的那部分。
除了直接使用分號結束定義,你還可以像一個普通的類一樣,通過提供一組大括號,并添加其他屬性和方法。編譯后,你仍然會得到編譯器自動生成的代碼。
其他限制
目前還暫時只支持記錄類(record classes)。在理論上,也能夠使用相同的基本語法和概念進行添加記錄結構體(record structs)。
類庫支持問題
在 .NET 中使用不可變類型(immutable types)有一個嚴重的限制,即它缺乏廣泛的類庫支持。想象一下,如果你是一個負責中間層的開發者,那你每日的工作很可能就是通過 ORM 從數據庫獲取一些對象,然后再序列化到 SOAP-XML 或 JSON,然后以單向或者雙向的方式傳遞給客戶端。
但是, 目前的大多數的 ORM 及序列化支持不可變類型(immutable types),它們會假定該類型具有一個無參數的構造函數,并且包含一些可變的屬性。如果這個問題沒有在這些流行的框架中解決,那么在大多數工程項目中記 錄類(record classes)將用處不大。
欲了解更多信息,請參見草案規范 Pattern Matching for C#。該原型應該可以在數周內發布。
<span id="shareA4" class="fl">
</span>