2009-04-19 63 views
30

所以,當我寫這樣的事情新的Action()和lambda有什麼區別?

Action action = new Action(()=>_myMessage = "hello"); 

重構臨!突出這是一個冗餘的代表創建,並允許我將其縮短到

Action action =() => _myMessage="hello"; 

而且這通常很好。 通常,但並非總是如此。例如,犀牛製品有一個名爲做一個擴展方法:

IMethodOptions<T> Do(Delegate action); 

這裏,通過在第一個版本的作品,但第二個沒有。這裏的封面到底是什麼?

+4

你的第二個代碼塊不進行編譯。我收到此消息「無法將lambda表達式分配給隱式類型的局部變量」。但是,如果我將「var」替換爲「Action」,它就可以。 – 2009-04-19 20:04:33

+1

是的,你是對的,它不能被分配給一個隱式類型的變量,我會編輯它。 – 2009-04-20 02:12:44

回答

47

第一版切實做好:

Action tmp =() => _myMessage = "hello"; 
var action = new Action(tmp); 

你正在運行到的問題是

有關此主題的詳細討論,您應該主題閱讀埃裏克利珀的博客文章編譯器必須知道lambda表達式應該轉換成什麼樣的委託(或表達式樹)。這就是爲什麼這樣的:

var action =() => _myMessage="hello"; 

實際上沒有編譯 - 它可以是任何委託型不帶參數,要麼沒有返回值或相同的返回類型爲_myMessage(這大概是string)。例如,所有的這些都是有效的:

Action action =() => _myMessage="hello"; 
Func<string> action =() => _myMessage="hello"; 
MethodInvoker action =() => _myMessage="hello"; 
Expression<Action> =() => _myMessage="hello"; 
// etc 

如何可以在C#編譯器是什麼類型action的意思是,如果它是用var申報?

調用一個方法(對於您的犀牛製品的例子)時避開這個最簡單的方法是投:

methodOptions.Do((Action) (() => _myMessage = "hello")); 
8

您是否驗證過第二行實際編譯的內容?它不應該編譯,因爲C#不支持將一個lambda表達式分配給一個隱式類型變量(CS0815)。這行可以在VB.Net中工作,因爲它支持創建匿名代理(從VB 9.0開始)。

由於第二行不能編譯的原因,Rhino Mocks版本不能編譯。 C#不會自動推斷出lambda表達式的類型。 Lambda表達式必須在可以確定它們要實現的委託類型的上下文中使用。第一行很好,因爲預期的類型很明確:Action。 Rhino Mocks版本不起作用,因爲Delegate更類似於抽象委託類型。它必須是一個具體的委託類型,例如Action或Func。 http://blogs.msdn.com/ericlippert/archive/2007/01/11/lambda-expressions-vs-anonymous-methods-part-two.aspx