C# 10 中對Lambda的語法和型別進行了多項改進:
1. Lambda自然型別
Lambda 表示式現在有時具有“自然”型別。 這意味著編譯器通常可以推斷出 lambda 表示式的型別。
到目前為止,必須將 lambda 表示式轉換為委託或表示式型別。
在大多數情況下,我們會在 BCL 中使用過載的 Func<...> 或 Action<...> 委託型別之一:
從 C# 10 開始,如果 lambda 沒有這樣的“目標型別”,.NET 將嘗試計算一個:
滑鼠懸停在 var parse 上,然後檢視型別仍然是 Func<int, string>
編譯器將使用可用的 Func 或 Action 委託(如果存在合適的委託)。 否則,它將合成一個委託型別.
並非所有 lambda 表示式都有自然型別——有些只是沒有足夠的型別資訊。 例如,放棄引數型別將使編譯器無法決定使用哪種委託型別:
lambda 的自然型別意味著它們可以分配給較弱的型別,例如 object 或 Delegate:
當涉及到表示式樹時,我們結合了“目標”和“自然”型別。 如果目標型別是 LambdaExpression 或非泛型 Expression(所有表示式樹的基型別)並且 lambda 具有自然委託型別 D,將改為生成 Expression<D>:
2. 方法組的自然型別
方法組(即沒有引數列表的方法名稱)現在有時也具有自然型別。.NET 能夠將方法組轉換為相容的委託型別:
現在,如果方法組只有一個過載,它將具有自然型別:
3. Lambda返回型別
在前面的示例中,Lambda表示式的返回型別是顯而易見的,並被推斷出來的。 但是也有特殊情況:
在 C# 10 中,可以在 lambda 表示式上指定顯式返回型別,就像在方法或本地函式上一樣。
返回型別在引數之前。
當指定一個顯式的返回型別時,引數必須用括號括起來,這樣編譯器或其他開發人員不會太混淆:
4. Lambda的屬性
從 C# 10 開始,可以將屬性放在Lambda 表示式上,就像對方法和本地函式一樣。 當有屬性時,Lambda 的引數列表必須用括號括起來:
就像本地函式一樣,如果屬性在 AttributeTargets.Method 上有效,則可以將屬性應用於 lambda。
Lambda 的呼叫方式與方法和本地函式不同,因此在呼叫 lambda 時屬性沒有任何影響。 但是,lambdas 上的屬性對於程式碼分析仍然有用,並且可以通過反射發現它們。
C#10新特性-lambda 表示式和方法組的改進
周國慶
2022/3/8