問題描述
C#2.0出現了匿名方法, 這在一定程度上節省了我們維護代碼內容相關的精力, 也不需要思考為某個方法取什麼名字比較合適. 在FCL的一些方法中要求傳入一個Delegate類型的參數, 比如Control.Invoke或者Control.BeginInvoke方法:
public object Invoke(Delegate method);public IAsyncResult BeginInvoke(Delegate method);
在這種情況下, 如果不使用匿名方法, 則需要在代碼的上面先聲明一個delegate void DoSomething()方法, 然後可以在Invoke方法中再用lambda運算式或者委託實現DoSomething().
delegate void DoSomething();private void App(){ XXControl.Invoke(new DoSomething(() => { //DoSomething的具體操作 }));}
這樣做可以是可以, 但使用匿名方法則更好, 最起碼看上去更簡潔.
private void App(){ XXControl.Invoke(delegate { //DoSomething的具體操作 });}
上面的代碼會在編譯的時候出錯: Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type. 方法要求參數的是一個委託(delegate)類型, 而現在傳遞的只是一個匿名方法. 產生這個錯誤最根本的原因是編譯器在處理匿名方法的時候, 沒法推斷出這個委託的方法返回的是什麼類型, 也就不知道返回一個什麼樣的委託.
解決方案
要解決上面這個問題, 從根本上來說就是指定這個匿名方法將會返回什麼類型的委託, 有幾種方法:
1. 使用MethodInvoke或者Action
private void App(){ XXControl.Invoke((MethodInvoker)delegate() { //DoSomething的具體操作 });}
private void App(){ XXControl.Invoke((Action)delegate() { //DoSomething的具體操作 });}
MethodInvoke和Action都是方法傳回型別為空白的委託.
2. 可以給Control定義一個Invoke的擴充方法
public static void Invoke(this Control control, Action action){ control.Invoke((Delegate)action);}
調用的時候則可以這樣調用:
//使用委託XXControl.Invoke(delegate { //DoSomething here});//使用lambda運算式XXControl.Invoke(()=>{ //DoSomething here});
參考
1. http://stackoverflow.com/questions/253138/anonymous-method-in-invoke-call
2. http://staceyw1.wordpress.com/2007/12/22/they-are-anonymous-methods-not-anonymous-delegates/