在 C# 2.0 之前的版本中,創建委托的唯一方式是使用命名方法。 從 C# 2.0 開始引入了匿名方法,而在 C# 3.0 以及更高的版本中,Lambda 表達式取代了匿名方法,從而作為編寫內聯代碼的首選方式。 不過,這裡有關匿名方法的信息同樣也適用於 Lambda 表達式。 需要注意的是,有一種情況,匿名方法它提供了 Lambda 表達式中所沒有的功能。 就是,你可以使用匿名方法來忽略參數列表。 這意味著匿名方法可以轉換為具有各種簽名的委托。 這對於 Lambda 表達式來說幾乎是不可能的。 有關 lambda 表達式的更多信息,我們下次再聊。
要將代碼塊傳遞為委托參數,創建匿名方法則是唯一的方法。
示例一:
// 創建一個點擊事件 button1.Click += delegate(Object o, EventArgs e) { MessageBox.Show("Click!"); };
示例二:
// 創建一個委托. delegate void MyDel(int x); // 使用匿名方法實例化委托 MyDel d = delegate(int k) { /* ... */ };
通過使用匿名方法,由於不必創建單獨的方法,從而減少了實例化委托所需的編碼系統開銷。
例如,如果創建方法所需的系統開銷是不必要的,則指定代碼塊(而不是委托)可能非常有用。 這個啟動新線程的示例即是一個很好的示例。 無需為委托創建更多方法,線程類即可創建一個線程並且包含該線程執行的代碼。
void StartThread() { Thread t1 = new Thread (delegate() { Write("Hello, "); WriteLine("World!"); });
t1.Start(); }
匿名方法的參數的使用范圍是“匿名方法塊”。
如果目標在塊外部,則在匿名方法塊內使用可以跳轉的語句(如 goto、break 或 continue)是錯誤的。 如果目標在塊內部,在匿名方法塊外部使用跳轉的語句(如 goto
、break
或 continue
)也是錯誤的。
如果局部變量和參數的范圍已經包含匿名方法聲明,則該局部變量和參數將被稱為該匿名方法的“外部”變量。 比如,這個代碼段中的 n
就是一個外部變量:
int n = 0; MyDel d = delegate() { WriteLine("#:{0}", ++n); };
外部變量的引用 n,將
被認為是在創建委托時進行捕獲,它與本地變量不同,所被捕獲的變量的在生存期內,會存活到引用該匿名方法委托被垃圾回收。
匿名方法不能訪問外部范圍的 ref 或 out 參數。
在“匿名方法塊”中不能訪問任何不安全代碼。
在 is 運算符的左側不允許使用匿名方法。
下面的示例演示實例化委托的方法,這兩種方法都會在調用委托時顯示一條消息:
使委托與匿名方法關聯。
使委托與命名方法 (DoWork
) 關聯。
// 聲明委托 delegate void Printer(string s); class MyClass { static void Main() { // 使用匿名方法實例化委托 Printer p = delegate(string j) { WriteLine(j); }; // 返回匿名委托所調用的結果 p("使用匿名方法調用委托。"); // 使用"Do"的命名的方法的委托實例化。 p = new Printer(TestClass.Do); // 使用舊的風格調用委托 p("使用命名方法調用委托。"); } // 後續用於委托調用 static void Do(string msg) { WriteLine(msg); } }