Search code examples
c#.netanonymous-methods

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.


Solution

  • 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.