开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜