Reputation: 23
Why changes to the outer data-source is not reflected, while they show-up for the inner data-source?? Pls help
public static void MyMethod(char[] inputDS1, char[] inputDS2)
{
Console.WriteLine("\n'from' clause - Display all possible combinations of a-b-c-d.");
//query syntax
IEnumerable<ChrPair> resultset = from res1 in inputDS1
from res2 in inputDS2
select new ChrPair(res1, res2);
//Write result-set
Console.WriteLine("\n\nOutput list -->");
displayList(resultset);
//swap positions
//obs: changes to the first ds is not reflected in the resultset.
char[] temp = inputDS1;
inputDS1 = inputDS2;
inputDS2 = temp;
//run query again
displayList(resultset);
Console.WriteLine("\n------------------------------------------");
}
Input:
('a','b'), ('c','d')
Output:
ac, ad, bc, bd, **aa. ab, ba, bb**
I expected all possible combinations (ac, ad, bc, bd, ca, cb, da, db) as I swapped the Data-sources before the second Write. When I do a ToList() before the second Write, I get the expected result, so is it because that Select is lazy? Please explain.
Update
What I tried was - to add a ToList() (to force immediate execution) to the query-expression after the ds-swap. And I got the proper results - ac, ad, bc, bd, ca, cb, da, db. This would return expected results.
//query syntax
IEnumerable<ChrPair> resultset = from res1 in inputDS1
from res2 in inputDS2
select new ChrPair(res1, res2);
//Write result-set
Console.WriteLine("\n\nOutput list -->");
displayList(resultset);
//swap positions
//obs: changes to the first ds is not reflected in the resultset.
char[] temp = inputDS1;
inputDS1 = inputDS2;
inputDS2 = temp;
resultset = (from res1 in inputDS1
from res2 in inputDS2
select new ChrPair(res1, res2)).ToList();
//run query again
displayList(resultset);
Upvotes: 2
Views: 662
Reputation: 33381
I think, the issue is that the first variable (inputDS1) don't included in any anonymous function (lambda) then the compiler wouldn't generate closure for it.
Compiler translates query to something like this:
IEnumerable<ChrPair> resultset =
inputDS1.SelectMany(c => inputDS2.Select(c1 => new ChrPair(c, c1)));
As you see, the inputDS1
is not contains in any anonymous(lambda). Instead, the inputDS2
contains in lambda then compiler will generate for it closure. Therefore, in your second execution of query you have access to modified closure inputDS2
.
Upvotes: 1
Reputation: 11597
what you got were combination from chars from inputDS1
with chars from inputDS2
. this is what the query
IEnumerable<ChrPair> resultset = from res1 in inputDS1
from res2 in inputDS2
select new ChrPair(res1, res2);
does, that's what you asked from it: "take 1 item from inputDS1
and 1 item from inputDS2
and combine the two to new ChrPair
"
EDIT
after understanding your question let me explain something very fundamental:
the line
IEnumerable<ChrPair> resultset = from res1 in inputDS1
from res2 in inputDS2
select new ChrPair(res1, res2);
does not return a list or IEnumerable<ChrPair>
. it return a method that has a source (inputDS1
) and an input. when you're swapping the two, you mess with the input of the method, but the source does not changed (it probably copied and not just referenced). when you do .ToList();
you activate the method, thus not getting any unexpected behavior due to commands called afterwards.
Upvotes: 1
Reputation: 834
From what I can see, the part
char[] temp = inputDS1;
inputDS1 = inputDS2;
inputDS2 = temp;
swaps around the input parameter and not the results you get from your linq statement.
Upvotes: -1