我发现了一些非常奇怪的东西,我希望能够更好地理解。
var all = new List<int[]>{
new int[]{1,2,3},
new int[]{4,5,6},
new int[]{7,8,9}
};
all.ForEach(n => n.ForEach(i => Console.WriteLine(i)));
可以改写为:
...
all.ForEach(n => n.ForEach(Console.WriteLine));
如何省略lambda表达式参数(i =&gt;)并且仍然将当前项传递给console.WriteLine?
感谢您的任何见解。 -Keith
答案 0 :(得分:33)
List<T>.ForEach
正在寻找Action<T>
。当你写
n.ForEach(Console.WriteLine);
您在此处拥有的方法组Console.WriteLine
的成员之一扮演Action<T>
角色。编译器将查找Console.WriteLine
的最佳重载,它会占用int
的实例。实际上,它将使用重载Console.WriteLine(int)
。然后,它将使用此重载来扮演Action<int>
。
有关如何完成此操作的详细信息,请参阅规范的§6.6(方法组转换)。
但是,当你写
时n.ForEach(i => Console.WriteLine(i));
我们实际上有一个非常不同的Action<int>
在第一种情况下,Action<int>
是Console.WriteLine(int)
。在这里,Action<int>
相当于你写的
public static void DoSomething(int i) {
Console.WriteLine(i);
}
然后
n.ForEach(DoSomething);
(当然,编译器必须经历与上述相同的方法组过程,以找出DoSomething
的含义。
重点是,在第一种情况下,Action<int>
是 Console.WriteLine(int)
。但是,在第二种情况下,Action<int>
是一个中间人(lambda表达式),它本身将调用Console.WriteLine(int)
。
答案 1 :(得分:2)
如果考虑到实际发生的事情,这就不那么容易混淆了。
您正在将方法传递给委托参数。大多数情况下,我们在事件的上下文中考虑代理,但它们也可以作为方法的参数。将方法添加到没有参数的事件时似乎并不奇怪,在此上下文中执行时只是异常。
在lambdas之前,你必须一直这样做,这是一种痛苦,人们永远不会考虑使用看起来像LINQ的库。使用Lambdas,这样做更容易,但您也可以使用旧方法。