delegate int Calculate(int a, int b);
static int Add(int a, int b) => a + b;
Calculate calc = new Calculate(Add); // 或 Calculate calc = Add; (方法群組轉換)
Calculate calc = delegate(int a, int b) { return a + b; };
Calculate calc = (a, b) => a + b; // 運算式主體
Calculate calc2 = (a, b) => { return a + b; }; // 陳述式主體
x => x * 2。() => DateTime.Now。以 Calculate calc = (a, b) => a + b; 為例,編譯器生成:
<Main>b__0(int a, int b) { return a + b; }static Calculate CS$<>9__CachedAnonymousMethodDelegate1;// 偽代碼對應 IL
if (CachedDelegate == null)
CachedDelegate = new Calculate(<Main>b__0);
calc = CachedDelegate;
IL 片段驗證:
IL_000c: ldnull
IL_000d: ldftn int32 Program::'<Main>b__0'(int32, int32)
IL_0013: newobj instance void Calculate::.ctor(object, native int)
IL_0018: stsfld class Calculate Program::'CS$<>9__CachedAnonymousMethodDelegate1'
若 Lambda 參考區域變數:
int factor = 10;
Func multiply = x => x * factor;
編譯器產生顯示類別 (Display Class):
[CompilerGenerated]
private sealed class <>c__DisplayClass0 {
public int factor;
public int <Main>b__0(int x) => x * factor;
}
區域變數 factor 被提升為顯示類別欄位,Lambda 實例化時捕捉該類別實例,延長變數生命週期。
指派給 Expression<Func<T>> 時,編譯器不生成 IL 方法,而是建構運算式樹 物件圖,供 LINQ to SQL、動態查詢等在執行期解析轉譯為 SQL。此為「程式碼即資料」的核心基礎。
list.Select(Foo) 優於 list.Select(x => Foo(x)),可直接使用現有方法指標。async (x) => await DoAsync(x) 返回 Task,注意例外處理與同步上下文捕捉。Lambda 表達式是語法糖,本質上編譯器為我們生成委派實例化與必要的顯示類別。理解其編譯降級過程,有助於寫出高效能、記憶體友善的程式碼,並掌握 LINQ、非同步程式設計的底層運作。