The answer to the following code is 5
Can someone explain why this is? If you were to replace int d1 = x.Current with d1 = x.Current and declare d1 above the while loop, the answer would be 2 and I understand why that is but I don't know why it's 5 otherwise.
IEnumerable<int> num = new []{10,11,12,13,14,15,16};
IEnumerable<int> div = new [] {2,3,5};
var lazy = Enumerable.Empty<int>();
var x = div.GetEnumerator();
while(x.MoveNext()){
int d1 = x.Current;
lazy = lazy.Concat(num.Where(s=>s % d1 == 0));
}
int count = lazy.Distinct().Count();
Console.WriteLine("{0}",count);
EDIT: Here is the snippet that gives you an answer of 2.
IEnumerable<int> num = new []{10,11,12,13,14,15,16};
IEnumerable<int> div = new [] {2,3,5};
var lazy = Enumerable.Empty<int>();
var x = div.GetEnumerator();
int d1;
while(x.MoveNext()){
d1 = x.Current;
lazy = lazy.Concat(num.Where(s=>s % d1 == 0));
}
int count = lazy.Distinct().Count();
Console.WriteLine("{0}",count);
(Peter beat me to the punch, but I was half done when his answer appeared, so I'll post it anyhow.)
You can get more insight into the difference by instrumenting the code. The instrumentation within the lambda expression is the thing that provides the crucial insight:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Baseline.");
Test1();
Console.WriteLine("Modified.");
Test2();
}
static void Test1()
{
IEnumerable<int> num = new[] { 10, 11, 12, 13, 14, 15, 16 };
IEnumerable<int> div = new[] { 2, 3, 5 };
var lazy = Enumerable.Empty<int>();
var x = div.GetEnumerator();
while (x.MoveNext())
{
int d1 = x.Current;
Console.WriteLine("d1 = " + d1);
lazy = lazy.Concat(num.Where(s => {bool result = s % d1 == 0; Console.WriteLine("s = " + s + ", d1 = " + d1); return result;}));
Console.WriteLine("lazy has " + lazy.Count());
}
Console.WriteLine("Evaluating lazy.Distinct().Count()");
int count = lazy.Distinct().Count();
Console.WriteLine("{0}", count);
}
static void Test2()
{
IEnumerable<int> num = new[] { 10, 11, 12, 13, 14, 15, 16 };
IEnumerable<int> div = new[] { 2, 3, 5 };
var lazy = Enumerable.Empty<int>();
var x = div.GetEnumerator();
int d1;
while (x.MoveNext())
{
d1 = x.Current;
Console.WriteLine("d1 = " + d1);
lazy = lazy.Concat(num.Where(s => {bool result = s % d1 == 0; Console.WriteLine("s = " + s + ", d1 = " + d1); return result;}));
Console.WriteLine("lazy has " + lazy.Count());
}
Console.WriteLine("Evaluating lazy.Distinct().Count()");
int count = lazy.Distinct().Count();
Console.WriteLine("{0}", count);
}
}
After "Evaluating lazy.Distinct().Count()" is printed, you'll notice two things that might surprise you.
First, that evaluation requires re-running the lambda expression that was declared within the loop. It is easy, but wrong, to think of "lazy" as a collection of integers. In fact it is a function for creating a collection of integers, so counting the distinct elements requires re-running that function.
Second, you'll notice that the values of d1 are different between the two evaluations. In the first case, d1 is 2, and in the second case d1 is 5. The reason for this is, as Peter Duniho pointed out, that declaring d1 outside the loop allows it to retain the value that it had when the loop finished (so you have 5, the last value in the div sequence), wherease declaring it within the loop requires re-computing it (so you have 2, the first element in the div sequence).
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