我有一个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...
}
正如您所期望的那样,按钮是使用正确的内容正确创建的,但是当我单击任何按钮时,MessageBox
内的文本始终是items
中的最后一个字符串。我错过了什么?为什么按钮的所有Click
函数都传递给集合中的最后一项?
答案 0 :(得分: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...
}
因此,您在声明时会引用s
的实例,而不是执行。