C#12 新功能 (2)

Collection Expressions,一個頗為方便的新功能,讓我們繼續看下去。

Collections Expressions 中文被稱為集合表達式,名字聽起來很厲害的樣子,說穿了就是更先進的集合初始化設定式。

目前這個功能可以用在陣列、Span<T> and ReadOnlySpan<T> 以及支持集合初始化設定式的集合型別 (但 Dictionary<T1,T2> 偏偏不行)。

不囉嗦,先來幾個簡單的範例:

 int[] array = [1, 2, 3, 4, 5, 6, 7, 8];

 List<string> list = ["one", "two", "three"];

 Span<char> span = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i'];

 int[][] towArray = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

 ObservableCollection<string> collection = ["A", "B", "C"];

使用這個表達式的時候,左邊的回傳型別必須明確指派,不可以偷懶用 var。

還有一個很有趣的用法,像這樣:

IEnumerable<int> GetSomethings() => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

不過我覺得上面回傳 IEnumerable<T> 的寫法看來雖然很炫,但是展開後的程式碼實在有點奇妙,會像這樣 (第一行我就直接用新語法表示,偷懶不展開了):

 IEnumerable<int> GetSomethings2()
 {
     int[] array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
     <>z__ReadOnlyArray<int> readOnlyCollection =new <>z__ReadOnlyArray<int>(array);
     return readOnlyCollection;
 }

會出現一個奇妙的型別 <>z__ReadOnlyArray<int> ,不要試圖在你的 C# 程式碼用這個型別,其中一個是因為這個型別的命名在 C# 是不合法的 (但 IL 層級是合法的,所以很多奇妙的型別都會帶<> 開頭),再來他是編譯器搞出來的,除非你硬用反射去搞他,不然也用不了。

另外一個有趣的部份是配合散布運算子 (spread operator),這個運算子的長相就是兩個點啦。

 List<int> list1 = [10, 11, 12];
 List<int> list2 = [.. list1, 20, 30];
 int[] array = [.. list1, 99, 98, .. list2];
 Console.WriteLine(string.Join(", ", array));

所以 list2 就是 list1 的元素加上新增的 20, 30;array 就是 list1 + 99 + 98 + list2,用起來的爽度很高。