4

Why the below code ouput 333 not 012? I think the code is so simple and I check and check and double check, triple check, can not get answer yet. Any one can help me?

Action[] tmp = new Action[3];

for (int i = 0; i < tmp.Length; i++)
{
    tmp[i] = () => Console.WriteLine(i);
}

Array.ForEach(tmp, m => m());

Console.Read();
Lee Taylor
  • 7,761
  • 16
  • 33
  • 49

2 Answers2

1

This occurs because there is only one i variable in the original code as for does not introduce a new variable "each loop" and the same variable is closed over in all the closures! As such, the same (i) variable is assigned the last value (3) before any of the functions are executed after the loop.

Compare with the following code which ensures a new variable to bind in each closure (this is one rare case where I use underscores for a local variable to show "something funny" is happening):

for (int _i = 0; _i < tmp.Length; _i++)
{
    int i = _i; // NEW/fresh variable, i, introduced each loop
    tmp[i] = () => Console.WriteLine(i);
}

This behavior (and complaints against) is discussed in detail in Is there a reason for C#'s reuse of the variable in a foreach? - for and foreach have this same "issue" in C#4 and before, which is "fixed" for foreach in C#5.

I think it is fair to say that all regret that decision. This is one of the worst "gotchas" in C#, and we are going to take the breaking change to fix it. In C# 5 the foreach loop variable will be logically inside the body of the loop, and therefore closures will get a fresh copy every time. - Eric Lippert

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
1

You should change your code to:

Action[] tmp = new Action[3];

for (int i = 0; i < tmp.Length; i++)
{
    int j = i;
    tmp[i] = () => Console.WriteLine(j);
}

Array.ForEach(tmp, m => m());

Console.Read();

The reason is closure is nest

More detailed information please see those links: Is there a reason for C#'s reuse of the variable in a foreach? http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/

Community
  • 1
  • 1
Weimin Ye
  • 665
  • 4
  • 15
  • 1
    Thank you very much. I immediately get the correct result use your code. Even your links are the same as other one provide. But you are the one give the code. So I accept your answer. But I also thank other guys. –  May 03 '14 at 02:19