在 2.0 以前的 C# 版本中,聲明委託的惟一方式是使用命名方法。 C# 2.0 引入匿名方法,在 C# 3.0 及更高版本中,Lambda 表達式取代匿名方法做爲編寫內聯代碼的首選方式。 可是,本主題中有關匿名方法的信息也適用於 Lambda 表達式。 在有一種狀況下,匿名方法提供 Lambda 表達式中沒有的功能。 使用匿名方法可省略參數列表。 這意味着匿名方法可轉換爲具備多種簽名的委託。 Lambda 表達式沒法實現這一點。 有關 Lambda 表達式的詳細信息,請參閱 Lambda 表達式。html
建立匿名方法其實是一種將代碼塊做爲委託參數傳遞的方式。 這裏是兩個示例:express
// 爲單擊事件建立處理程序 button1.Click += delegate(System.Object o, System.EventArgs e) { System.Windows.Forms.MessageBox.Show("Click!"); };
// 建立一個委託. delegate void Del(int x); // 使用匿名方法實例化委託 Del d = delegate(int k) { /* ... */ };
因爲使用匿名方法無需建立單獨的方法,所以可減小對委託進行實例化的編碼開銷。編程
例如,在因不得不建立方法而可能出現非必要開銷的狀況下,指定代碼塊(而不是委託)頗有用處。 開始新線程就是一個很好的示例。 此類建立一個線程,且還包含該線程執行的代碼,而無需爲委託建立其餘方法。安全
void StartThread() { System.Threading.Thread t1 = new System.Threading.Thread (delegate() { System.Console.Write("Hello, "); System.Console.WriteLine("World!"); }); t1.Start(); }
備註ide
匿名方法的參數範圍爲匿名方法塊。ui
若是目標在匿名方法塊以外,匿名方法塊內具備 goto、break 或 continue 等跳轉語句是一種錯誤。 若是目標在匿名方法塊以內,匿名方法塊外具備 goto
、break
或 continue
等跳轉語句也是一種錯誤。編碼
範圍包含匿名方法聲明的本地變量和參數稱爲此匿名方法的外部變量。 例如,在以下代碼段中,n
是一個外部變量:spa
int n = 0; Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };
建立委託時,對外部變量 n
的引用被視爲已捕獲。 不一樣於本地變量,已捕獲的變量的生存期一直延伸至引用匿名方法的委託具備垃圾回收資格爲止。線程
匿名方法沒法訪問外部範圍的 in、ref 或 out 參數。指針
沒法在匿名方法塊內訪問任何不安全代碼。
不容許在 is 運算符左側使用匿名方法。
以下示例演示實例化委託的兩種方式:
將委託與匿名方法相關聯。
將委託與命名方法 (DoWork
) 相關聯。
在每一種狀況下,調用委託時均顯示一條消息。
// 定義委託. delegate void Printer(string s); class TestClass { static void Main() { // 使用匿名方法實例化委託類型 Printer p = delegate(string j) { System.Console.WriteLine(j); }; // 匿名委託調用的結果 p("The delegate using the anonymous method is called."); // 使用命名方法「DoWork」的委託實例化 p = DoWork; // 傳統方式委託調用的結果 p("The delegate using the named method is called."); } // 與命名委託關聯的方法。 static void DoWork(string k) { System.Console.WriteLine(k); } } /* 輸出: The delegate using the anonymous method is called. The delegate using the named method is called. */
其餘更詳細的技術請參考: