首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 匿名方法完整指南:變數捕獲、外部變數生命週期、多播疊加與平台優勢深度解析

     編輯:關於C#

C# 2.0 引入匿名方法,消除「為了委派必須寫具名函式」的樣板碼。編譯器自動生成隱藏類別封裝捕獲變數,實現閉包語義,運行期效能與具名函式幾乎相同,生產力大幅提升。

基礎語法


delegate void Action();

// 匿名方法賦值給委派
Action a = delegate { Console.WriteLine("Hello"); };
a();

// 帶參數
delegate void ActionT(string msg);
ActionT b = delegate(string m) { Console.WriteLine(m); };
b("World");

變數捕獲與外部變數

匿名方法可存取定義範圍外的區域變數(外部變數),編譯器將其「提升」為隱藏類別的欄位:


void Demo() {
    string name = "Zach"; // 外部變數
    Action a = delegate { Console.WriteLine(name); };
    a(); // 輸出 Zach
    name = "Smith"; // 修改外部變數
    a(); // 輸出 Smith - 捕獲的是變數本身,非值快照!
}
  • 捕獲的是變數,非值。外部變數修改對匿名方法可見
  • 外部變數生命週期延長至委派存活期間,即使原方法返回
  • ref/out 參數不能被捕獲

編譯器降級實現原理


// 來源
int i = 0;
Action a = delegate { i++; };

// 編譯器產生 (簡化)
class __DisplayClass {
    public int i;
    public void __Anonymous() => this.i++;
}
// 使用
var ctx = new __DisplayClass { i = 0 };
Action a = ctx.__Anonymous;
  • 每個捕獲作用域產生一個顯示類別
  • 巢狀作用域產生巢狀顯示類別,子類別持有父類別參考
  • 同一作用域多個匿名方法共享同一顯示類別實例

多播疊加


Action a = delegate { Console.WriteLine("1"); };
a += delegate { Console.WriteLine("2"); }; // 疊加
a(); // 輸出 1 然後 2
a -= delegate { Console.WriteLine("1"); }; // 移除需相同委派實例,通常保存引用

作為參數傳遞


void Execute(Action a) => a();
Execute(delegate { Console.WriteLine("Inline"); });

存取類別成員


class Demo {
    int _counter = 0;
    void Run() {
        Action a = delegate { Console.WriteLine(_counter++); };
        a(); // 0
        a(); // 1 - 捕獲 this,存取實例欄位
    }
}

平台優勢總結

  1. 語法簡潔:就地定義行為,無需跳轉
  2. 閉包語義:自然捕獲上下文,支援函數式模式
  3. 零額外開銷:編譯器降級為具名方法,JIT 優化同等
  4. 演進相容:Lambda (C# 3.0) 為匿名方法語法糖,底層機制同源

避坑指南

  • ⚠️ 迴圈中捕獲迴圈變數:for(int i=0;i<10;i++) actions.Add(delegate{Console.Write(i);}); → 全輸出 10。修正:int j=i; actions.Add(delegate{Console.Write(j);});
  • ⚠️ 長壽命委派捕獲大型物件 → 記憶體洩漏。必要時手動 del = null 釋放
  • ⚠️ ref/out 不可捕獲,需用區域變數中轉

匿名方法是 C# 邁向函數式程式設計的關鍵一步,掌握其捕獲語義與編譯器實現,能寫出更簡潔、更具表達力的代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved