2011-02-07 2 views
10

하나의 코드가 컴파일에 실패하고 다른 코드가 제대로 컴파일되는 이유에 대한 좋은 설명을 찾고 있습니다.왜 lambda 문 괄호로 인해 구문 오류가 발생합니까?

실패 :

richTextBox1.Invoke(new MethodInvoker((() => { richTextBox1.AppendText("test"); }))); 

는 방법 이름이 바로 MethodInvoker( 후 여는 괄호에

예상

오류를 제공합니다. 분명히, 나는 괄호 안에 람다 문을 감쌀 수 없다.

컴파일 :

richTextBox1.Invoke(new MethodInvoker(() => { richTextBox1.AppendText("test"); })); 

질문입니다 - 왜?

나는 원하는 경우 괄호 안에 메서드 param을 래핑 할 수 있다고 항상 당연히 생각했지만 분명히 람다 식의 경우는 그렇지 않습니다. 나는 그것들이 다소 특별하다는 것을 이해하지만, 나는 아직도 이것에 대한 좋은 이유를 볼 수 없다. 어쩌면 내가 구문에 대해 뭔가를 이해하지 못할 수도 있습니다. 나는 정말로 그것을 얻고 싶다.

덧붙여서, 이것은 VS2008, .NET 3.5 SP1에서, VS2010과 .NET 4에서는 아직 테스트하지 않았습니다.

답변

7

를 호출 할 수 있습니다, 그것은을 포함하는 괄호 표현입니다 람다 식. 따라서이 메소드 호출에 대한 추상 구문 트리의이 매개 변수에 대한 노드는 괄호로 묶인 표현식이되며 사양에서 요구하는 람다식이 아닙니다. 이는 이유.

Microsoft C# 컴파일러가 사양을 위반하지 않으며 (규격별로) 사용하지 않아도되지만 이러한 표현을 허용하는 다른 곳이 있지만 그 중 하나가 아닙니다.

사양의 관련 섹션은 §6.5입니다.

+0

감사합니다. 호기심에서 벗어나 - 그 장소의 예를 제공해 주시겠습니까? – Dyppl

+3

@Dyppl :'Func F() {return (() => 1); }'는 합법적이지만 스펙에 따르면 안된다. – jason

+0

감사합니다! 글쎄, 내 질문에 대해 좀 더 기분이 좋다. 이러한 불일치로 인해 결국 머리가 엉망이 될 것입니다. – Dyppl

3

Invoke() 메서드 내에서 컴파일러는 ()=>{}을 예상하므로 첫 번째 예제에서는 찾을 수 없습니다. 괄호 안의 모든 것이 먼저 평가되어 단일 객체를 반환합니다.이 경우 컴파일러는 델리게이트에 대한 참조를 기대합니다. 나는이 확장 방법과 같은 문제를 해결 한

편집 :

public delegate void EmptyHandler(); 
    public static void SafeCall(this Control control, EmptyHandler method) 
    { 
     if (control.InvokeRequired) 
     { 
      control.Invoke(method); 
     } 
     else 
     { 
      method(); 
     } 
    } 

그래서 당신은 그것은 람다 식 아니다

RichTextBox rtb = new RichRextBox(); 
... 

rtb.SafeCall(()=> rtb.AppendText("test")); 
+3

는 사실, 익명의 대표도 문법 설탕 있습니다을; C# 컴파일러는 람다 구문을 익명의 대리자 구문으로 변환하지 않습니다. 두 가지를 모두 구체적인 함수 (또는 클로저에 따라 함수가있는 클래스)와 전통적인 대리자로 변환합니다. –

4

"메서드 매개 변수"를 작성했다고 착각했습니다. 만든 구조가 메서드 호출이 아니므로 대리자 만들기 식을 작성했습니다 (C# 사양, 7.6.10 절 참조).5) 하나

  • 방법 그룹이어야 하나의 인자,
  • 익명 함수 또는
  • 동적 컴파일시 타입 중 하나의 값 또는 델리게이트 타입을하도록되어있는 . 이 "어딘가의 내부는"익명 함수를 포함하는 표현이기 때문에 귀하의 경우에는

, 그것은 ((오류 메시지가 메소드 이름이 예상되는 것을 암시)하는 방법 그룹 않으며, 익명 함수가 아닙니다) 또는 상기 유형의 값도 아니다. 당신이 방법 invokation을 썼다면

, 당신은, 참으로, 그것은 람다 식 포함되어있는 경우에도, 괄호 안에 매개 변수를 래핑 수 :

void Method(Action action) 
{ 
} 
... 
Method((() => { Console.WriteLine("OK"); })); 
관련 문제