2013-05-19 88 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