Search code examples
c#delegatesanonymous-methodsclosures

Closures in C# event handler delegates?


I am coming from a functional-programming background at the moment, so forgive me if I do not understand closures in C#.

I have the following code to dynamically generate Buttons that get anonymous event handlers:

for (int i = 0; i < 7; i++)
{
    Button newButton = new Button();

    newButton.Text = "Click me!";

    newButton.Click += delegate(Object sender, EventArgs e)
    {
        MessageBox.Show("I am button number " + i);
    };

    this.Controls.Add(newButton);
}

I expected the text "I am button number " + i to be closed with the value of i at that iteration of the for loop. However, when I actually run the program, every Button says I am button number 7. What am I missing? I am using VS2005.

Edit: So I guess my next question is, how do I capture the value?


Solution

  • To get this behavior, you need to copy the variable locally, not use the iterator:

    for (int i = 0; i < 7; i++)
    {
        var inneri = i;
        Button newButton = new Button();
        newButton.Text = "Click me!";
        newButton.Click += delegate(Object sender, EventArgs e)
        {
            MessageBox.Show("I am button number " + inneri);
        };
        this.Controls.Add(newButton);
    }
    

    The reasoning is discussed in much greater detail in this question.