通常,當我們使用代理時,我們總是有一個方法。該方法的簽名匹配代理的 簽名規定並且能被用來初始化一個代理實例。匿名方法用於把方法和代理的初始 化壓縮到一個單一的位置。
通過使用前一節的例子,我們已看到代理new EventHandler的實例化是怎樣 區別於用來初始化該代理的方法OnClick的。這部分代碼能被壓縮成一個匿名方 法:
private void Form1_Load(object sender, EventArgs e){
button1.Click += delegate
{
Debug.WriteLine("button1 clicked");
};
}
為了創建該匿名方法,請注意我們刪除了OnClick的方法頭並且用OnClick的 方法體的單詞delegate代替了EventHandler代理的構造器。其所導致的結果行為 是相同的。如果我們想使用事件參數,我們通常與代理相關聯,我們可以在單詞 delegate之後添加一可選的參數列表:
private void Form1_Load(object sender, EventArgs e){
button1.Click += delegate(object s, EventArgs ev)
{ Debug.WriteLine("object is " + s.ToString()); };
}
如果你定義代理參數,它們必須匹配代理類型所定義的參數。例如,Click的 類型是EventHandler,因此如果參數存在,它們必須匹配EventHandler的參數對 象和EventArgs。
匿名方法可以被使用在任何需要使用代理的地方。匿名方法可以使用ref和 out參數,但是不能使用全局范圍的reference ref或out參數。匿名方法不能使 用unsafe編碼,並且匿名方法不能以使得分支行為跳出匿名方法的代碼塊的方式 來使用goto,break或continue等語句。
四、市場調查結果
匿名方法是好東西嗎?市場調查證明匿名方法確實不錯,因為它們能夠減少 由於實例化代理和減少分離方法所導致的代碼開銷。而且市場調查還證明匿名方 法增強了可用性和可維護性。我認為良好命名的方法也可以實現這一點。請看下 面的代碼容易維護嗎?
private void Form1_Load(object sender, EventArgs e)
{
BindClick(delegate { Debug.WriteLine("button1 click"); });
}
private void BindClick(EventHandler handler)
{
button1.Click += handler;
}
在這個例子中,我們把一個代理傳遞給一個方法-通過把該代理作為一個匿名 方法傳遞。僅是保持圓括號、分號和方括號的順序和個數就已令人十分頭疼。
如果引用經典示例來說明,那就是匿名方法僅僅是因剔除了線程(它們使用代 理)而減少了相應的創建代理和方法的開銷。這倒是真的,但是線程並不經常使 用並且想正確使用也非常困難。我在想,要想使代碼更為秘密些而不是更為公開 些該是多麼謹慎的一件事情。
就語言方面來講,我喜歡方法;但是作為一個實際開發中的事物,匿名方法 也許僅是微軟的某個發明者有點太聰明的一種證明。
五、總結
匿名方法是可以存在沒有名字的方法的證明-它們可以被定義並使用在任何能 夠使用代理的地方。代理是事件處理器的包裝器。匿名方法到底有多大的實用性 和普遍使用價值還有待於進一步的實踐證明。我懷疑,匿名方法將不會比運算符 重載有更大的用途,並且其使用也會少之又少;但是匿名方法現在已是.Net的一 部分,所以在閱讀代碼時能夠識別出它們來還是很有必要的。