1

I am currently working on a WinForm-Project, where I am adding custom controls to a panel depending on the response of a web-server. I am also setting an Action on these custom controls, but am experiencing behaviour, that I find quite odd. I don't want to bore you with too much code, so I made some example code to demonstrate the problem:

Action[] actionArr = new Action[3];

for (int i = 0; i < 3; i++)
{
    actionArr[i] = () => { Console.WriteLine(i.ToString()); };
}

foreach (var cur in actionArr)
{
    cur();
}

What I expect the code to do, is to add 3 different Actions to the Action-Array, but when executing this code I get the following output:

3
3
3

Really, it should never output a 3, since the for-loop exits, before i reaches 3.

After some experimenting I found a really odd solution to this problem. I added the following function:

private static void setArr(ref Action[] arr, int i)
{
    arr[i] = () => { Console.WriteLine(i.ToString()); };
}

And I changed the for-loop to:

for (int i = 0; i < 3; i++)
{
    setArr(ref actionArr, i);
}

With this code I get the output, I expected:

0
1
2

Is there a logical reason behind why C# does this? And what is the proper way of doing it?

e.g.
  • 11
  • 1
  • Hint: what happens if you put a breakpoint on `Console.WriteLine(i.ToString())`? – Ian Kemp Feb 26 '21 at 13:13
  • 1
    A better dupe might be https://stackoverflow.com/questions/451779/how-to-tell-a-lambda-function-to-capture-a-copy-instead-of-a-reference-in-c – Ian Kemp Feb 26 '21 at 13:14
  • you can just create new int which you assign to i and than use that in your action – Bonny4 Feb 26 '21 at 13:25

0 Answers0