2015-02-24 113 views
2

假設我有此委託的聲明:Delegate.Combine和lambda表達式

private delegate UInt32 Feedback(UInt32 value); 

在這裏,我嘗試用lambda表達式

feedback = (Feedback)Delegate.Combine(feedback, 
     value => { Console.WriteLine("Lambda item = " + value); return 0; }); 

使用它,但我得到的錯誤:無法轉換lambda表達式鍵入'System.Delegate',因爲它不是委託類型

但是它的工作原理是這樣的

feedback = (Feedback)Delegate.Combine(feedback, 
     new Func<UInt32, UInt32>(value => { Console.WriteLine("Lambda item = " + value); return 0; })); 

我以爲C#編譯器必須自己做。

回答

5
feedback = (Feedback)Delegate.Combine(feedback, 
    (Feedback)(value => { Console.WriteLine("Lambda item = " + value); return 0; })); 

您必須明確說出lambda函數的類型,否則編譯器不知道它具有哪種類型。例如看到http://blogs.msdn.com/b/jaredpar/archive/2007/12/14/c-lambda-type-inference.aspx

One of the limitations of C# type inference is that you cannot use it to infer the type of a lambda expression. For example, the following code will not compile

var f =() => 4; 
+0

是因爲* value *是一個值類型,編譯器不能使用Contra-variance? – Yola 2015-02-24 08:49:53

+0

@Yola編譯器如何知道值是否是一個uint?它可以是任何類型 – 2015-02-24 08:51:38

+0

@Yola不,這是因爲'Delegate.Combine'具有參數'Delegate',並且通過查看您的函數,它無法知道參數的類型(什麼是「值」?一個字符串),即使它知道參數/返回值的類型,.NET中的「相似」委託之間也沒有等效(類似委託=具有相同簽名的委託) – xanatos 2015-02-24 08:51:51

2

拉姆達沒有一個類型。它可以隱式轉換爲兼容的委託類型。

Delegate.Combine需要Delegate作爲參數,因爲Delegate是一個沒有任何簽名的抽象類,lambda表達式不能轉換爲Delegate。您只能將lambda轉換爲具有兼容簽名的具體類型。

如果您希望編譯器將您的lambda轉換爲Delegate類型,它是一個抽象類,因此無法實例化 - 您希望編譯器選擇哪種具體類型?你必須指定它。

您可以顯式指定類型是這樣的:

feedback = (Feedback)Delegate.Combine(feedback, new Feedback(value => { Console.WriteLine("Lambda item = " + value); return 0; })); 

在另一方面,如果你有在LHS具體的委託類型,編譯器會很樂意進行編譯。

例如:以下是一個有效的C#代碼。因爲你說編譯器需要將它轉換爲Feedback委託類型。

Feedback feedback2 = value => { Console.WriteLine("Lambda item = " + value); return 0; }; 
3

Lambda表達式沒有在C#類型,除非你施放them.It是因爲一個拉姆達可以轉換爲一個以上的delegate類型,因此編譯器不能決定哪一個choose.And也有沒有辦法確定什麼是拉姆達參數的類型,因爲你沒有指定它們。