The following gives answer as 1 in VS 2010 and 2 in VS 2012. I personally think it should be 2. I am not sure what's going on here.
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;
namespace _335ExamPreparation
{
public class Doubts
{
int[] nums = { 10, 11, 12, 13, 14, 15, 16 };
int[] divisors = { 7, 10 };
static void Main(string[] args)
{
Doubts d = new Doubts();
d.func();
}
public void func()
{
var m = Enumerable.Empty<int>();
foreach (int d in divisors)
{
m = m.Concat(nums.Where(s => (s % d == 0)));
}
int count = m.Distinct().Count();
Console.WriteLine(count);
}
}
}
Thanks.
What you're seeing is the result of two different applications of foreach
. The behavior was changed in VS 2012. See this article.
The difference between the two involves the scope and lifetime of the d
variable in the foreach
loop. Before VS 2012, there was only one d
variable, so what this means is that you are creating two copies of a closure (s => (s % d == 0))
) that both reference the same d
. After the loop finishes being evaluated, d
is 10. When you execute the query by calling .Distinct().Count()
, both closures will see a value of 10 for d
. This is why the count is 1 on VS 2010.
VS 2012 generates a different variable for each iteration1, so each closure will see a different instance of the d
variable, the one that corresponds to that particular iteration.
This is roughly the code that VS 2010 generates:
int d;
for (int _index = 0; _index < divisors.Length; ++_index) {
d = divisors[_index];
m = m.Concat(nums.Where(s => (s % d == 0)));
}
And this is roughly what VS 2012 generates:
for (int _index = 0; _index < divisors.Length; ++_index) {
int d = divisors[_index];
m = m.Concat(nums.Where(s => (s % d == 0)));
}
The difference between these two should be readily apparent.
If you want to get the same behavior no matter which VS version, then always copy your iteration variable:
foreach (int d in divisors)
{
var copy = d;
m = m.Concat(nums.Where(s => (s % copy == 0)));
}
1 Technically, only if the iteration variable is referenced in a closure. If it's not then there is no need to make a copy as this only affects closure semantics anyway.
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