0

I encountered this strange behavior with captured variables. Below are two loops. I would expect both to behave the same. Why it behaves differently?

        private static void Loop1()
    {
        var actions = new List<Action>();
        foreach (var number in Enumerable.Range(1, 5))
        {
            actions.Add(()=>Console.WriteLine(number));
        }
        foreach (var currentAction in actions)
        {
            currentAction();
        }
    }

    private static void Loop2()
    {
        var actions = new List<Action>();
        for (int number = 0; number <= 4; number++)
        {
            actions.Add(() => Console.WriteLine(number));
        }
        foreach (var currentAction in actions)
        {
            currentAction();
        }
    }

The first loops print 1,2,3,4,5 The second loop prints 5,5,5,5,5

Hunter
  • 2,370
  • 2
  • 20
  • 24
  • what are the results of both? In what way are the results different? – user1666620 Nov 04 '16 at 15:45
  • 9
    C# 5 changed this. https://blogs.msdn.microsoft.com/ericlippert/2009/11/12/closing-over-the-loop-variable-considered-harmful/ – SLaks Nov 04 '16 at 15:46
  • 2
    Yup - basically `Loop2` only has a single `number` variable, whereas `Loop1` has a fresh "instantiation" of the `number` variable for each iteration of the loop. – Jon Skeet Nov 04 '16 at 15:47
  • Yup, prior to C#5, both printed 5,5,5,5,5. It was a deliberate change, justified by the fact the foreach loop doesn't really imply whether there is one number variable reused through the whole loop, or a different number variable created for each iteration, and most people wanted and expected the latter. The for loop syntax makes it pretty obvious that there's only one number variable to capture. – PMV Nov 04 '16 at 17:01

0 Answers0