Lambda事件处理程序范围

时间:2012-04-12 14:13:06

标签: c# delegates 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 个答案:

答案 0 :(得分:2)

最后两个将无法编译,因为在完成分配之前无法引用e

第一个有效,因为此限制不适用于字段。

您可以先将null分配给EventHandler e = null; e = (o, s) => { somectl.LayoutUpdated -= e; }; somectl.LayoutUpdated += e; ,以便明确分配最后一个。

{{1}}

答案 1 :(得分:2)

这与lambdas的关系不如你想象的那么多。例如,这会失败:

int i = i + 1;

就像这样:

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

或者:

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

lambda表达式失败的原因相同:中间的表达式因为你不能在其声明中引用任何变量,而最后一个因为你无法保证在你尝试之前已经初始化了e在lambda中使用它。

第一个示例正常工作,因为 fields 总是被初始化。它们将在类的构造函数中被赋予一个值,或者它们将自动设置为它们的默认值。如果你想在方法的范围内完成这项工作,你只需要在声明它时分配你的变量。

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

答案 2 :(得分:0)

在最后两种情况下,编译器可以检查您是否正在使用lambda中的未分配局部变量。在第一种情况下,由于全局变量,编译器无法检查它。