4

我在理解以下代码给我错误的原因时遇到了一些麻烦:

 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 必须始终直接或通过执行委托创建表达式 new D(F) 转换为委托类型 D 或表达式树类型 E。这种转换决定了匿名函数的结果。”

4

1 回答 1

2

原因很简单:

编译如何得出它应该是的结论Func<int, int>?他简直不能!

假设您有自己的委托:

 public delegate int F(int i);

编译器如何在 和 之间进行Func<int, int>选择F?这些是完全不同的类型,有两个共同点:都有委托并且具有相同的签名(一个参数和返回类型,都是 type 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);

一个小优势:你可以inty.

于 2013-05-19T16:49:01.233 回答