.NET 3.5 內建三大委派家族,配合 Lambda 運算式極大簡化程式碼:
| 委派 | 型別參數 | 對應方法簽章 | 用途 |
|---|---|---|---|
Func<TResult> | 最後一個為回傳型別 | TResult Method() | 有回傳值的運算 |
Func<T, TResult> | 前 N-1 為參數,最後為回傳 | TResult Method(T arg) | 轉換/投影 |
Action<T> | 參數型別 | void Method(T arg) | 執行動作(無回傳) |
Predicate<T> | 參數型別 | bool Method(T arg) | 條件判斷/篩選 |
以下 Lambda:
Func<string> f = () => "abc";
編譯器產生私有靜態方法:
.method private hidebysig static string '<Main>b__0'() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 1
.locals init ([0] string CS$1$0000)
IL_0000: nop
IL_0001: ldstr "abc"
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
}
本質上,Lambda 只是編譯器自動產生方法並包裝為委派的語法糖。
static 類別中staticthis 修飾,指明擴充對象
public class Test1 { public string String1 { get; set; } public int Int1 { get; set; } }
public static class Test2
{
public static string AddDefaultPage(this Test1 t)
{
return t.String1 + "/Default.ASPx";
}
}
// 呼叫
var t4 = new Test1 { String1 = "https://xianfen.Net", Int1 = 0 };
t4.AddDefaultPage(); // 如同實例方法
擴充方法編譯為靜態方法呼叫:
.call string CS30NEW.Test2::AddDefaultPage(class CS30NEW.Test1)
若實例方法與擴充方法同名同簽章,實例方法優先。擴充方法無法存取 private/protected 成員。
查詢語法(from...where...select)編譯為擴充方法鏈結,最終皆為 Enumerable 靜態方法呼叫。CLR 版本維持 2.0,所有魔法由編譯器完成。
.NET 3.x 未變更 CLR/IL,純粹透過編譯器語法糖與框架擴充方法,賦予開發者更高表達力。理解其本質,有助於除錯、效能調優與進階擴充。