I executed the following code with C# 3.5 and 4.0. The results are entirely different.
static void Main()
{
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
List<IEnumerable<int>> results = new List<IEnumerable<int>>();
foreach (var num in numbers)
{
results.Add(numbers.Where(item => item > num));
}
foreach (var r in results)
{
Console.WriteLine("{0}", r.Count());
}
}
With Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.5420 the output is 0 0 0 0 0 0 0 0 0 0
.
But with Microsoft (R) Visual C# Compiler version 4.0.30319.17929 the output is 9 8 7 6 5 4 3 2 1 0
.
I have a faint idea that this is because of deferred execution or lazy evaluation but haven't clearly understood how it is responsible for different outputs here.
Correction: Sorry it was .NET 3.5 and 4.5 and also added compiler versions Please explain.
Since c# 5, the loop variable in foreach
is compiled such that it exists within the loop scope rather than outside it.
This means that when you close over the loop variable, you get different results.
Here's what Eric Lippert had to say about the original problem.
You have accessed a variable inside a closure, therefore the results will differ on different versions of the compiler.
In C# 5.0, the variable is redefined in each iteration of the loop, whereas in previous C# versions it was only defined once.
For more info, see Eric Lippert's great blog post
More notably, the opening paragraph:
UPDATE: We are taking the breaking change. In C# 5, the loop variable of a foreach will be logically inside the loop, and therefore closures will close over a fresh copy of the variable each time. The "for" loop will not be changed. We return you now to our original article.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With