【问题标题】:Problem with different "execution context" of an anonymous method within a loop循环内匿名方法的不同“执行上下文”问题
【发布时间】:2011-05-23 12:13:52
【问题描述】:

我对循环中的匿名方法有疑问。

下面的代码只是为了说明我的问题:

private void Form1_Load(object sender, EventArgs e)
{
    List<string> bassists = new List<string>(){
        "Jaco Pastorius", 
        "Marcus Miller", 
        "Flea", 
        "Vicor Wooten"
    };

    foreach (string item in bassists)
    {
        this.button1.Click += (s, ea) => Output(s, ea, item); 
    }
}

private void Output(object s, EventArgs e, string item)
{
    this.listBox1.Items.Add(item);
}

当我点击按钮时,输出是:

维克多·伍顿
维克多·伍顿
维克多·伍顿
维克多·伍顿

代替:

雅科·帕斯托瑞斯
马库斯·米勒
跳蚤
维科尔伍顿

我的问题的要点是不同的执行上下文。我知道我的例子很愚蠢。

【问题讨论】:

  • Jaco Pastorius、Marcus Miller、Flea 和 Victor Wooten。其中之一与其他不同......
  • 4 种不同的风格……但我都喜欢!

标签: c# .net anonymous-methods


【解决方案1】:

这是捕获变量问题。通过更改来修复它

foreach (string item in bassists)
{
    this.button1.Click += (s, ea) => Output(s, ea, item); 
}

foreach (string item in bassists)
{
    string currentItem = item;
    this.button1.Click += (s, ea) => Output(s, ea, currentItem); 
}

以下是对该问题的解释:Closing over loop variable considered harmful。通过将局部变量 currentItem 放在循环范围内并关闭它,我们现在捕获该变量而不是循环变量。

【讨论】:

  • 你也可以使用索引循环
  • @Falcon:使用索引循环有什么好处?
  • @Cody:我猜 Falcon 的意思是在范围内使用 for(int i...) 字符串是必要的;-)
【解决方案2】:

您的问题是您正在循环中创建新的处理程序,这是不必要且危险的。

此外,您正在创建一个匿名方法,该方法具有硬编码循环中的值。那更糟。

【讨论】:

    【解决方案3】:

    在任何情况下,杰森的回答都是正确的。这是变量捕获的问题。这主要发生在线程和匿名方法两种情况

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-13
      相关资源
      最近更新 更多