2

Here is the sample code.

var values = new List<string>() { "Stack", "Over", "Go" };

var funcs = new List<Func<string>>();

foreach(var v in values) 

  funcs.Add( ()=>v );
foreach(var f in funcs) 

  Console.WriteLine(f());

When I ran this code with visual studio 2010 I got the output as: Go Go Go

But when I tried the same code in visual studio 2012 the output was: Stack Over Go

Why is it behaving differently?

Zlatin Zlatev
  • 3,034
  • 1
  • 24
  • 32
Rajeev Ranjan
  • 1,006
  • 8
  • 18

1 Answers1

9

The reason is that the compiler was changed to create a temporary copy of variables captured in a closure.

Take the following code in VS 2012:

foreach(var v in values) 
    funcs.Add(() => v);

The code the VS 2012 compiler generates from this is equivalent to code generated by the VS 2010 compiler for this code:

foreach(var v in values) 
{
    var tmp = v;
    funcs.Add(() => tmp);
}

The reason for this change was the fact that many developers found the behaviour of the VS 2010 compiler unexpected.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • 1
    +1. See also: Eric Lippert's blog post on this topic: http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx – Ergwun Feb 25 '13 at 11:36
  • It's so nice to stop making loop copies of variables everywhere - always felt so dumb having to do it all the time. – Jon Egerton Feb 25 '13 at 11:36
  • @Ergwun: Thanks - I was just searching for that link to add something official. – Daniel Hilgarth Feb 25 '13 at 11:38
  • Well if we're going for official then the [page that tells you the differences between C# in Visual Studio 2010 and C# in Visual Studio 2012](http://msdn.microsoft.com/en-us/library/vstudio/hh678682.aspx) would be a good resource to look at/Google for. – ta.speot.is Feb 25 '13 at 11:39
  • @ta.speot.is: As Eric was a developer on the C# team, that's official enough for me. Furthermore, it is much more understandable than the overview. – Daniel Hilgarth Feb 25 '13 at 11:40
  • The point of my comment was to imply that if you Googled for *c# in visual studio 2012 differences* and could be bothered looking so far as the second link, the first item on the page explains exactly this behaviour. i.e. extreme laziness on someone's behalf... – ta.speot.is Feb 25 '13 at 11:43
  • 1
    @ta.speot.is: I am not really sure how to take your comment. If you are implying that I am lazy - that's laughable. If you are implying that the OP is lazy - that's debatable, but also not really fair. As a beginner, he most likely will be overwhelmed with the search results and the overview page. – Daniel Hilgarth Feb 25 '13 at 11:56
  • OP's question could be answered by the second link of a Google search. Yes, he is lazy. – ta.speot.is Feb 25 '13 at 11:57