开发者

C# method group strangeness

I discovered something very strange that I'm hoping to better understand.

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)));

which can be rewritten as:

...
all.ForEach(n => n.ForEach(Console.WriteLine));

How is i开发者_高级运维t possible to leave out the lambda expression parameter (i=>) and still have the current item passed to console.WriteLine?

Thanks for any insight. -Keith


List<T>.ForEach is looking for an Action<T>. When you write

n.ForEach(Console.WriteLine);

what you have here is one of the members of the method group Console.WriteLine playing the role of an Action<T>. The compiler will look for the best overload of Console.WriteLine that eats instances of int. In fact, it will use the overload Console.WriteLine(int). It will then use this overload to play the role of an Action<int>.

For details on how this is done, see §6.6 of the specification (Method group conversions).

However, when you write

n.ForEach(i => Console.WriteLine(i));

we actually have a very different Action<int> In the first case, the Action<int> was Console.WriteLine(int). Here, the Action<int> is equivalent to you having written

public static void DoSomething(int i) {
    Console.WriteLine(i);
}

and then

n.ForEach(DoSomething);

(Of course, the compiler has to go through the same method group process as described above to figure out what is meant by DoSomething).

The point is that in the first case the Action<int> is Console.WriteLine(int). However, in the second case the Action<int> is a middle man (the lambda expression) that itself will call Console.WriteLine(int).


This is less confusing if you consider what is really happening.

You are passing a method to a delegate argument. Most of the time, we think of delegates in the context of events, but they can be parameters to methods as well. It doesn't seem odd when a method is added to an event without arguments, it just is unusual looking when executed in this context.

Before lambdas, you had to do this all the time, and it was such a pain that one would never consider using a library that looked like LINQ. With Lambdas, this is easier to do, but you can always do the old way as well.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜