2012-04-12 4 views
4

사람이 좋아하는 이유의 깊이 explaination에, 나에게 설득력을 줄 수 :람다 이벤트 핸들러의 범위

EventHandler e; 

private void foobar(){ 
    e = new EventHandler((o, s) => { 
      somectl.LayoutUpdated -= e; 
    } 
    somectl.LayoutUpdated += e; 
} 

하지만이되지 않습니다 :

private void foobar(){ 
    EventHandler e = new EventHandler((o, s) => { 
      somectl.LayoutUpdated -= e; 
    } 
    somectl.LayoutUpdated += e; 
} 

아니다 이것이다 :

private void foobar(){ 
    EventHandler e; 
    e = new EventHandler((o, s) => { 
      somectl.LayoutUpdated -= e; 
    } 
    somectl.LayoutUpdated += e; 
} 
+3

어떤 오류가 발생합니까? – SLaks

+0

이 주제에 대한 내 기사를 참조하십시오 : http://blogs.msdn.com/b/ericlippert/archive/2006/08/18/why-does-a-recursive-lambda-cause-a-definite-assignment-error. aspx –

답변

2

이것은 생각보다 람다와 관련이 적습니다. 예를 들어,이 실패 :

int i = i + 1; 

을 것이 같이

int i; 
if (condition) {i = 0;} 
i = i + 1; 

또는 :

int i; 
if (condition) {Console.WriteLine(i);} 
i = 1; 

표현이 같은 이유로 실패 람다 : 당신이 할 수 있기 때문에 가운데 하나를 ' t는 선언 내에서 변수를 참조하고 마지막은 e이 람다 안에서 사용하려고 시도하기 전에 초기화되었음을 보장 할 수 없기 때문입니다.

필드이 항상 초기화되므로 첫 번째 예제는 정상적으로 작동합니다. 클래스의 생성자에 값이 주어 지거나 자동으로 기본값으로 설정됩니다. 메서드의 범위 내에서이 작업을 수행하려면 변수를 선언 할 때 변수를 지정하면됩니다.

private void foobar(){ 
    EventHandler e = null; 
    e = new EventHandler((o, s) => { 
      somectl.LayoutUpdated -= e; 
    } 
    somectl.LayoutUpdated += e; 
} 
2

할당을 완료하기 전에 e을 참조 할 수 없기 때문에 마지막 두 컴파일이 수행되지 않습니다.

첫 번째 것은이 제한이 필드에 적용되지 않기 때문에 작동합니다.

null에 먼저 할당하여 작업을 할당 할 수 있습니다.

EventHandler e = null; 
e = (o, s) => { 
     somectl.LayoutUpdated -= e; 
}; 
somectl.LayoutUpdated += e; 
0

마지막 두 경우에 컴파일러는 람다 내부에서 할당되지 않은 로컬 변수로 작업하고 있는지 확인할 수 있습니다. 첫 번째 경우에는 전역 변수 때문에 컴파일러에서이를 확인할 수 없습니다.

관련 문제