這篇筆記要整理的是 C# 10 針對 lambda 語法的改進。
C# 10 的 lambda 語法有四項改進,首先要介紹的是自動推斷委派型別(inferred delegate type)。範例:
Func<string> hello = () => "Hello World";
Console.WriteLine(hello());
此範例在 C# 9 可以通過編譯。到了 C# 10,則因為編譯器能夠自動推斷委派型別而可以使用 var
來宣告委派變數,像這樣:
var hello = () => "Hello World"; // C# 9 無法編譯!
如果委派的回傳值為 null,編譯器自然無法判定你想回傳什麼型別,例如:
var hello = () => null; // 無法編譯!
此時如果還是想要用 var
來宣告變數型別,則可以在撰寫 lambda 表達式的時候宣告回傳型別:
var hello = string? () => null; // OK!
當你的程式有很複雜的巢狀 lambda 語句,便可使用這種明確宣告回傳型別的方式來減輕編譯器推斷型別的負擔,從而加快編譯速度。這是 lambda 語法的第二項改進。
第三項改進是當我們把 lambda 表達式傳入某方法的參數時,參數型別可以是 object
、Delegate
、或 Expression
:
M1(() => "test"); // Func<string>
M2(() => "test"); // Func<string>
M3(() => "test"); // Expression<Func<string>>
void M1(object x) { }
void M2(Delegate x) { }
void M3(Expression x) { }
在 C# 9,第 1 行至第 3 行都無法通過編譯(無法將 lambda 表達式轉換成目標參數型別),C# 10 則沒有問題。
最後一項改進是,lambda 表達式從現在開始可以套用特徵項(attribute),包括匿名方法、方法參數、以及回傳值,皆可套用。範例:
var fn1 = [Description("是在哈囉")] () => "Hello";
var fn2 = ([Description("參數") string s) => "Hello " + s;
var fn3 = [Description("是在哈囉")]
[return: Description("回傳字串")]
([Description("參數")] string s) => "Hello " + s;
說明:
- 為
fn1
的匿名方法套用 DescriptionAttribute,也就是替方法加上說明文字。 - 為
fn2
的匿名方法加上參數的說明文字。 - 為
fn3
的匿名方法、參數、回傳型別都加上說明文字。
使用時機:某些 API 會去判斷傳入的委派方法是否套用了某種特徵項而有不同的行為,此時便可使用 C# 10 新增的 lambda 特徵項語法來撰寫匿名方法,而不用像以前那樣非得撰寫具名方法不可。
Happy coding!
沒有留言: