In C # 5 onwards, the foreach declares a separate variable i for each iteration of the loop. Thus, each closure captures a separate variable, and you see the expected results.
In the for loop, you have only one variable i , which is fixed by all closures and changes as the cycle progresses - therefore, by the time delegates are called, you will see the final value of this only variable.
In C # 2, 3, and 4, the foreach also behaved in a way that in principle was never the desired behavior, so it was fixed in C # 5.
You can achieve the same effect in a for loop if you introduce a new variable in the body area of the loop:
for (int i = 3; i <= 4; i++) { int copy = i; actions.Add(() => Console.WriteLine(copy)); }
For more information, read Eric Lippert's blog post, “Closing on a loop variable is considered harmful” - Part 1 , Part 2 .
source share