2013-05-19 160 views
4
我有一點麻煩了解背後爲什麼下面的代碼是給我一個錯誤的原因

lambda表達式和類型推斷

var funs = Enumerable.Range(0, 10).Select(x => (int y) => x + y); 
foreach (var fun in funs) 
    Console.WriteLine("{0}", fun(10)); 

的錯誤是「一個隱式類型的局部變量聲明不能初始化'System.Collections.Generic.IEnumerator.Current'「。我知道如何解決它(通過指定選擇類型,如Select<int, Func<int, int>>或通過使用一個輔助方法,如private static Func<T1, TR> MakeFunc<T1, TR>(Func<T1, TR> f) { return f; }和使用Select(x => MakeFunc(y => x + y))

不過,我想明白其中的道理,編譯器不能根據7.15.6,我最好的猜測是,它無法弄清楚它是否應該將內部lambda轉換爲Func或Expr。我是正確的還是有更多的東西?

僅供參考,這裏是7.15.6說:

「一位不願具名的函數F必須始終轉換爲委託類型d或表達式目錄樹類型E,無論是直接或通過executi代表創建表達式新D(F)。這種轉換決定了匿名函數的結果「

+0

嘗試在代碼塊中包裝您返回的lambda,看看會發生什麼? –

+0

這個編譯? –

+1

這可能有所幫助:http://stackoverflow.com/a/4966409/1223622 –

回答

1

原因很簡單:?!

怎麼能編譯得出結論,它應該是Func<int, int>他簡單的不能

假設你有你自己的委託: ?

public delegate int F(int i); 

怎麼能編譯器的Func<int, int>F之間進行選擇,這些是完全不同的類型,有兩個共同點:有兩個代表和有相同的簽名(一個參數和返回類型,都是int)。

所以編譯器不能選擇;你將不得不這樣做:

var funs = Enumerable.Range(0, 10).Select<int, Func<int,int>>(x => y => x + y); 

var funs = Enumerable.Range(0, 10).Select<int, F>(x => y => x + y); 

一個小的優勢:您可以將y之前刪除int