C# 14 新功能還有一些比較無法長篇描述的就集中在這裡一次說完。
null-conditional assignment
在 C# 6.0 的新功能中 null conditional operator 是非常重要的一步,這使得我們可以不需要為了檢查是否為 null 而寫出一大串的判斷式,例如你以前可能需要這樣寫:
if (person != null && person.Address != null )
{
var city = person.Address.City;
}在 C# 6.0 之後就能簡化成:
var city = person?.Address?.City;但是,就是這個但是,當時 null conditional operator 沒有辦法放在指派運算子的左邊,這功能終於在 C# 14 完善了,現在我可以大膽地這樣寫:
person?.Address?.City = "taipei";nameof supports unbound generic types
這個功能簡單解釋就是以前要使用 nameof 運算式取得泛型型別名稱的時候,泛型參數必須是 close type,例如:
var c1 = nameof(List<int>); // c1 is "List"C# 14 則可以使用 open type
var c2= nameof(List<>); // c2 is "List"看起來很廢,但具有幾個重要的意義:
- 不需要為了 nameof 硬是填一個不相干的型別進泛型參數,在意圖上的表達較為明確
- 和 typeof 表達式一致,typeof 本來就可以使用 open type
- 有一個比較特殊的情境是假設是自訂了一個名為 MyList<T> 泛型類別,而你在程式碼中使用了 nameof(MyList<int>);過了不久後你的同事將 MyList 的泛型參數加入約束為參考型別,那你所有使用 nameof(MyList<int>) 的程式碼都會從正常變成編譯錯誤,如果使用 nameof(MyList<>) 就能避免這類問題。
Modifiers on simple lambda parameters
進一步簡化 Lambda,過往 Lambda 的參數遇到修飾詞的時候必須要明確地宣告參數型別,這一次改善這個問題,例如
delegate bool TryParse<T>(string s, out T result);
delegate void SpanAction(scoped ReadOnlySpan<char> span);
delegate void ReadOnlyRefAction<T>(ref readonly T value);
internal class Program
{
static void Main(string[] args)
{
TryParse<int> tryParse = (text, out result) => int.TryParse(text, out result);
SpanAction print = (scoped x) => Console.WriteLine(x.Length);
ReadOnlyRefAction<int> write = (ref readonly x) => Console.WriteLine(x);
}
}目前可以省略參數型別的修飾詞有 ref、out、in、scoped 與 ref readonly,至於 params 截至目前還是需要明確宣告其陣列型別。
Implicit span conversions
這是一個比較不容易感受的改變,沒錯,它就是要讓你不容易感受。
這個功能簡單來說,就是將轉型為 Span<T> 或 ReadOnlySpan<T> 的行為從 API 層級升等到編譯器層級。例如有以下兩個擴充方法,其參數分別為 ReadOnlySapn<char> 與 ReadOnlySpan<T>:
public static class MyExtensions
{
public static void Display(this ReadOnlySpan<char> span)
{
for (int i = 0; i < span.Length; i++)
{
Console.Write(span[i]);
}
Console.WriteLine();
}
public static void Show<T>(this Span<T> span)
{
foreach (var item in span)
{
Console.Write($"{item} ");
}
Console.WriteLine();
}
}先看呼叫 Display 方法的過去與現在:
string text = "Hello, World!";
text.AsSpan().Display(); // 過去,需要先轉換為 ReadOnlySpan<char>,
text.Display(); // 現在,可以直接呼叫擴充方法,編譯器會處理轉換為 ReadOnlySpan<char> 的程序呼叫 Show 方法的過去與現在:
/* 過去, 必須先轉換為 ReadOnlySpan<int> */
var array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
ReadOnlySpan<int> readOnlySpan = array;
readOnlySpan.Show();
/* 現在,可以直接呼叫擴充方法,編譯器會處理轉換為 ReadOnlySpan<char> 的程序 */
array.Show();C# 14 的新功能就介紹到這篇,下次見。