2010-02-09 4 views
13

나는 내가 더 잘 이해하기를 바라고있는 이상한 것을 발견했다.C# method group strangeness

로 다시 작성할 수 있습니다
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))); 

: 여전히 현재 항목이 console.WriteLine에 통과는 람다 식의 매개 변수 (I =>)를 생략하는 것이 가능하고, 어떻게

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

?

어떤 통찰력에도 감사드립니다. - 키스

답변

33

Action<T>을 찾고 있습니다. 당신이

n.ForEach(Console.WriteLine); 

을 쓸 때 당신이 여기에있는 것은 Action<T>의 역할을하는 방법 그룹 Console.WriteLine의 구성원 중 하나입니다. 컴파일러는 int 인스턴스를 먹는 Console.WriteLine의 가장 좋은 오버로드를 찾습니다. 사실 과부하는 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); 

(무엇을 의미하는지 알아 내기 위해 전술 한 바와 같이 물론, 컴파일러는 같은 방법으로 그룹의 과정을 거쳐야한다 by DoSomething).

첫 번째 경우에 Action<int>Console.WriteLine(int)입니다. 그러나 두 번째 경우에 Action<int>은 중간 사람 (람다 식)으로 Console.WriteLine(int)을 호출합니다.

+1

++ Console.WriteLine의 과부하를 "먹는"컴파일러 이미지입니다. –

+1

매우 멋지게 표현되어 있습니다. 고맙습니다! – Keith

+0

좋은 설명. –

2

실제로 일어나는 일을 고려하면 혼란을주지 않습니다.

대리자 인수에 메서드를 전달하고 있습니다. 대부분의 경우, 우리는 이벤트 컨텍스트에서 대리자를 생각하지만 메서드에 대한 매개 변수가 될 수도 있습니다. 메소드가 인수없이 이벤트에 추가 될 때 이상하게 보이지는 않습니다.이 컨텍스트에서 실행될 때를보기는 어렵습니다.

lambdas 전에는 항상이 작업을 수행해야했으며, LINQ처럼 보인 라이브러리는 사용하지 않는 것이 좋습니다. Lambdas를 사용하면이 작업을 더 쉽게 수행 할 수 있지만 언제나 이전 방법을 사용할 수도 있습니다.

+0

C# 2.0은 익명의 delegate 문법 ('delegate() {}')을 가졌지 만 여전히 문법적으로 충분한 설탕이 아니었고 LINQ가 꽤 엉망이되었습니다. – Gabe