0

So I have some an int x I need to pass to another function, the problem is x changes before I use the function, so the value x changes to a different value than I want it. Is there a way to duplicate an integer (I couldn't find one)? That would solve my problem.

private void Init()
{
    for (int x = 0; x < 10; x++)
    {
        for (int y = 0; y < 10; y++)
        {
            Button tmpButton = new Button();
            tmpButton.Click += (sender, e) => ButtonClick(sender, e, x, y); 
            //x and y need to "freeze" their value at this point
        }
    }
}

private void ButtonClick(object sender, EventArgs e, int x, int y)
{
    Console.Out.WriteLine(x.ToString() + ":" y.ToString());
}

Output: "10:10"

Expected Output (if clicked on button 3,4): "3:4"

Andy G
  • 19,232
  • 5
  • 47
  • 69
Dane Bouchie
  • 421
  • 5
  • 11
  • You could simply store the values in the Tag then retrieve them in the eventhandler. – JasonSec May 16 '14 at 18:54
  • Good idea, but how do I store two int values in a tag? I could convert the matrix to linear (Ex: 10*x + y), but I don't really want to have to convert it back. – Dane Bouchie May 16 '14 at 18:56
  • As @JasonSec says, you need to put them in the `Tag` for each button. Either use a `Point` or some other custom `struct` to encapsulate them and put them in the tag as one thing. – ClickRick May 16 '14 at 18:59
  • I was thinking an array of int but Point works quite well for this situation nice suggestion :) – JasonSec May 16 '14 at 19:01

2 Answers2

2

This is a closure problem and is solved by using a temp variable

int localX = x;
int localY = y;

To better understand captured variables, see Jon Skeet's answer to this SO

Community
  • 1
  • 1
Justin Pihony
  • 66,056
  • 18
  • 147
  • 180
1

You should use a temporary variable:

for (int x = 0; x < 10; x++)
{
    for (int y = 0; y < 10; y++)
    {
        int tempX = x;
        int tempY = y;
        Button tmpButton = new Button();
        tmpButton.Click += (sender, e) => ButtonClick(sender, e, tempX, tempY); 
        //x and y need to "freeze" their value at this point
    }
}

You should always be careful when you are capturing variables in loops.

Basically, what happens is that your lambda is capturing the variables and not the value of the variables. So when the button is pressed, the loop is of course finished, and the value of the variables are 10.

Eric Lippert have written a great series on why this happens.

MAV
  • 7,260
  • 4
  • 30
  • 47
  • Oh yeah! For some reason I was thinking that I had to create a matrix for each temp. variable, when initializing the variable inside the matrix creates its own set. Thanks for the solution! – Dane Bouchie May 16 '14 at 19:00