我在循环中遇到匿名方法的问题。
以下代码只是为了说明我的问题:
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);
}
当我点击按钮时,输出为:
Victor Wooten
Victor Wooten
Victor Wooten
Victor Wooten
而不是:
Jaco Pastorius
马库斯米勒 跳蚤
Vicor Wooten
我的问题的主要问题是不同的执行上下文。我知道我的例子是愚蠢的。
答案 0 :(得分:12)
这是捕获的变量问题。通过更改
来修复它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
放在循环的范围内并关闭它,我们现在捕获该变量而不是循环变量。
答案 1 :(得分:0)
你的问题是你在循环中创建新的处理程序,这是不必要和危险的。
此外,您正在创建一个匿名方法,该方法的循环中的值具有硬编码。更糟糕的是。
答案 2 :(得分:0)
无论如何,杰森的回答是正确的。这是变量捕获的问题。这将主要发生在两种情况下的线程和匿名方法