Lambdas和类型推断

时间:2013-05-19 15:58:30

标签: c# .net delegates lambda type-inference

我在理解以下代码为什么会出现错误的原因时遇到了一些麻烦:

 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,直接或通过执行委托创建表达式new D(F)。此转换确定匿名函数的结果。“

1 个答案:

答案 0 :(得分:2)

原因很简单:

编译如何得出结论:它应该是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);

一个小优点:您可以将int放在y之前。