迭代List并使用匿名函数内的对象

jmc*_*thy 0 c# silverlight lambda

我有一个List<string>,我想迭代这个集合,并在按钮点击时对每个字符串做一些事情.我在这里有一个小例子来说明我正在尝试做的事情:

//items is a System.Collections.Generic.List<string>
foreach (string s in items)
{
    Button b = new Button() { Content = s };
    b.Click += (obj, ev) =>
    {
        MessageBox.Show(s);
    }
    //add b to form, container, etc...
}
Run Code Online (Sandbox Code Playgroud)

正如您所期望的那样,按钮是使用正确的内容正确创建的,但是当我单击任何按钮时,其中的文本MessageBox始终是最后一个字符串items.我错过了什么?为什么Click按钮的所有功能都传递给集合中的最后一项?

Fem*_*ref 8

所述foreach回路被改变s,这是在lambda使用.lambda使用s执行点的当前值,而不是声明它(在techspeak中:"闭包关闭变量,而不是值").你必须创建一个局部变量:

foreach (string s in items)
{
    string local = s;
    Button b = new Button() { Content = s };
    b.Click += (obj, ev) =>
    {
        MessageBox.Show(local);
    }
    //add b to form, container, etc...
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以参考sdecleration 的实例,而不是执行.

Eric Lippert有两篇关于它的精彩文章:第1 部分,第2部分.