LINQ foreach iteration variable capturing and how it's fixed in Visual Studio 11 - StrathWeb

Strath

March 16th, 2012

LINQ foreach iteration variable capturing and how it’s fixed in Visual Studio 11

Cause closures are confusing

A while a go, the C# community got surprised by another GOTCHA, discovering that using a foreach iteration variable inside a LINQ query, may not always yield the expected results. The variable gets captured by the foreach loop and, due to the evil work of closure, it remains scoped outside of the LINQ query itself living its own life so to speak. This has now been corrected in the Visual Studio 11 Beta.

Consider a simple example. Let’s start with a very basic Team class. Here it is.

Ok, now let’s take a generic list of our Team objects. We’ll also need an Enumerable to iterate through (in our case 4 iterations is enough ,as it corresponds to the List size), and a container for IEnumerable results of LINQ query we are gonna execute.

Alright, so far so good. Let’s loop through the Enumerable and use the iteration variable to select the Team from the collection and add it to the list container. Easy-peasy.

Now all we gotta do is just loop through the result list, and in there loop through IEnumerable and display the results.

This is definitely not rocket since, so it’s easy to predict the output.

  • Maple Leafs
  • Canadiens
  • Oilers
  • Senators

Right? Gotcha. Visual Studio 2010 produces this.

This problem lies in the foreach loop, which captured the iteration variable and kept changing it upon every iteration, thus affecting whatever we stored in the List<IEnumerable<string>>. A solution would be to introduce a new variable, copy the iteration’s variable value into it, and pass it to LINQ query instead.

Thankfully, this has been corrected in Visual Studio 11 Beta. Executing the same code in VS11b produces the following output, as expected.

So, if you have some old code that has been misbehaving, or you needed to copy variables inside the loop to avoid it, all you need to do now to resolve it is to recompile your code using VS11b.

Be Sociable, Share!

  • Pingback: WindowsDevNews.com

  • Olivia

    Very interesting info!Perfect just what I was searching for!

  • Julian

    Great job!

    • Filip W

      Thanks!

  • Edward Bumstead

    Keep functioning ,impressive job!

  • Daffi

    What a great resource!

  • jophez

    Great info! shared it with my team…greetings from the philippines!