前言
C# 12 是 .NET 8 版本推出的,目前還在 RC 階段。預計 2023 年 11 月份就會正式推出了。
想提早玩玩的話可以使用用 Visual Studio Preview。
參考
Primary Constructors
參考:
Docs – Tutorial: Explore primary constructors
YouTube – The New Constructor Type Coming in C# 12 is Weird
C# 9.0 推出的 Record 就有 Primary constructors 的概念。
它的 definition 非常短
public record Dimension(int Width, int Height);
相同的邏輯,class 就很長很繁瑣。
public class Dimension { public int Width { get; set; } public int Height { get; set; } public Dimension(int width, int height) { Width = width; Height = height; } }
於是,C# 12 也讓 class 和 struct 有了 primary constructors 的功能。
但是要注意哦,它們有一些些微妙的不同,很容易讓你掉坑。
Class primary constructors != Record primary constructors
public class Dimension(int width, int height);
上面這句和 Record 語法類似,但是效果卻差很多。
首相,它的參數是 camelCase,Record 是 PascalCase,爲什麼呢?
因爲 Record 的參數是 public property,而 class 的 parameter 是 private field。
所以,property 的寫法應該是長這樣的。
public class Dimension(int width, int height) { public int Width { get; set; } = width; public int Height { get; set; } = height; }
不管怎樣,它還是比之前短了一些。還是不錯用的。
Parameters can be use anywhere
參數不僅僅可以用於 assign to property,它也可以在方法中使用。
public class Dimension(int width, int height) { public int Sum() { return width + height; } }
原因上面提到了,paramters 其實是 private filed 來的
我們把代碼放到 sharplab.io 查看就明白了
簡單說,primary constructors 就是語法糖,它就是替你寫了一個 constructor 還有 private fields.
Dependency Injection
C# 11
public class Dimension { private readonly Service _service; public Dimension(Service service) { _service = service; } }
C# 12
public class Dimension(Service service) { private readonly Service _service = service; }
如果你不是很在意 readonly 的話,可以省略
public class Dimension(Service service) { }
本來聽說會支持 readonly 語法
public class Dimension(readonly Service service) { }
但最後視乎是被否決掉了。
總結
C# 12 以後,Record, Class, Struct 又又又更加像了,更傻傻分不清楚了,更容易掉坑了。
記住,class 的 primary constructors 是 constructor + private fields, Record 則是 constructor + public properties。
Collection Expressions
日常我們定義 collection 的方式
var numbers = new List<int> { 1, 2, 3 };
上面是 var 推導類型的 defined 寫法
換成先 declare 類型是這樣
List<int> numbers = new() { 1, 2, 3 };
C# 12 對上面這句語法做了優化,現在只需要這樣寫
List<int> numbers = [1, 2, 3];
它只是語法糖而已,通過 sharplab.io 查看
轉譯出來就是 new List + add item
Spread Operator
寫過 JavaScript 的人對 spread operator 應該不陌生了。C# 12 也有了這個功能。
var numbers = new List<int> { 1, 2, 3 }; List<int> numbers2 = [..numbers, 4, 5]; // 語法正確 var number3 = new List<int> { ..numbers2, 6, 7 }; // 語法錯誤哦
Default lambda parameters
C# 11 lambda 是不支持 default parameter value 的。C# 12 以後支持了。
C# 12
如果動態創建表達式樹 for default parameters 我還沒有研究。以後補上。
Alias any type
Alias type 有點像 TypeScript 的 Type Aliases,但也不完全一樣。
我目前是沒有想到哪裏可以用它啦。
using Point = Coordinate; public class Coordinate { public int X { get; set; } public int Y { get; set; } }
它可以完全用一個 alias 別名取代任何類型,就真的是 rename 而已哦。
var point = new Point();
上面這個在 TypeScript 是做不到的哦