C# 9.0 已經進入準備正式公開的階段,讓我們來預覽一下有哪些新鮮玩意兒。
環境
Visual Studio 2019 - 16.8.0 Preview 3.1
.NET 5.0.0-rc.1.20451.14
Visual Studio 2019 - 16.8.0 Preview 3.1
.NET 5.0.0-rc.1.20451.14
基本形式
第一個要介紹的是 Init only setter,它其實就是一個 property setter,但是限制外部僅能在物件初始化設定式中設定此屬性值;這裡使用 init 來取代 set 表明它的作用。先來一個簡單的範例:
class Person
{
public string Name { get; init; }
public int Age { get; init; }
}
在 Person 類別裡面,表明了 Name 和 Age 這兩個屬性的設定行為,想當然耳使用物件初始化設定式是沒有問題的。但當你想使用指派運算子指派新的值給這些屬性的時候,就會發生錯誤,以下方的程式碼為例, p1.Name = "Tom"; 這一行就會導致編譯例外。
var p1 = new Person() { Name = "Bill", Age = 12 };
p1.Name = "Tom";
那可否在建構式設定這些屬性呢?答案是可以的,以下程式碼為合法形式:
class Person
{
public string Name { get; init; }
public int Age { get; init; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
public Person()
{ }
}
至於結構型別能否使用 init only setter?答案也是可以,例如:
struct Circle
{
public double Radius { get; init; }
}
這帶來甚麼改變
去年 twMVC#36 我聊了一個題目『C#的美麗與哀愁』,當時提到了 C# 的未來發展會更傾向於非同步和函數式,而這兩個議題中有個很重要的觀念是「Immutable object (不可變物件)」,過去實現不可變物件有個麻煩就是必須完全透過建構式來進行,對於 setter 的部分要嘛就是移除,或是留個小洞變成 private setter,例如以下程式碼:
class Rectangle
{
public double Width { get; }
public double Height { get; }
public Rectangle (double width, double height)
{
Width = width;
Height = height;
}
}
這也可以運作的不錯,但是在屬性多的時候,光寫這個建構式大概就煩死人了;init only setter 提供了一個撰寫不可變物件更為簡潔方案,不需要再煩惱建構式的問題。而且這個新功能會和另一個新個功能 record 有關係,我們下次再聊。