Problem with different "execution context" of an anonymous method within a loop
I have a problem with an anonymous method within a loop.
The following code is just to illustrate my problem:
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);
}
And when I click into the button, the output is:
Victor Wooten
Victor Wooten Victor Wooten Victor Wooten
instead of:
Jaco Pastorius
Marcus Miller Flea Vicor Wooten
The main point of my problem is the differents execution context. I know my example is stupid.
This is the captured variable problem. Fix it by changing
foreach (string item in bassists)
{
this.button1.Click += (s, ea) => Output(s, ea, item);
}
to
foreach (string item in bassists)
{
string currentItem = item;
this.button1.Click += (s, ea) => Output(s, ea, currentItem);
}
Here is an explanation of the issue: Closing over loop variable considered harmful. By putting the local variable currentItem
in the scope of the loop and closing over that, we now capture that variable instead of the loop variable.
Your problem is that you are creating new handlers in the loop, that is unnecessary and dangerous.
Also you are creating an anonymous method which has the value in the loop hard-coded. That is worse.
In whatever cases Jason's answer is correct. It is problem of variable capturing. This will majorly occur in two situation Threading and Anonymous methods
精彩评论