2012-04-12 2 views
4

Может кто-нибудь дать мне красноречивый, в глубине объяснений, почему это нормально:Lambda сфера обработчик события

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 будет инициализирован, прежде чем пытаться использовать его в лямбда.

Первый пример работает отлично, потому что поля всегда инициализируются. Они либо получат значение в конструкторе класса, либо автоматически будут установлены по умолчанию. Если вы хотите сделать эту работу в рамках метода, вам просто нужно назначить свою переменную при ее объявлении.

2

Последние два не будут компилироваться, потому что вы не можете ссылаться на e, прежде чем завершить его.

Первый работает, поскольку это ограничение не распространяется на поля.

Вы можете сделать последнюю работу, предварительно назначив ее null, чтобы она была определенно назначена.

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

В последних двух случаях компилятор может проверить, что вы работаете с неназначенной локальной переменной внутри лямбда. В первом случае из-за глобальной переменной компилятор не может это проверить.

Смежные вопросы