Two subsequent FROM clauses get translated into a call to SelectMany.
a)
var query = from c_1 in collection_1
from c_2 in collection_2
from c_3 in collection_3
select ...
Correct me if I’m wrong, but I think query expression gets translated into a code semantically equivalent to:
collection_1.SelectMany(c_1 => c_1.collection_2.
SelectMany(c_2 => c_2.collection_3.
Select(c_3 => ... )));
Is from c_3 in collection always “bound” to c_2 range variable? With the term “bound” I’m asking whether the entire collection_3 gets enumerated for each c_2 element?
b) Assuming I’m correct under a), is c_3 always “bound” to range variable defined closest to it?
c) If answer to b) is true, then c_3 is bound to c_2 even in the following example:
var query = from c_1 in collection_1
from c_2 in collection_2
where ...
from c_3 in collection_3
d) Is in next query c_3 bound to a ( ie for each a the entire groupAandB will be enumerated ):
var query_1 = from a in groupA
join b in groupB on a equals b
into groupAandB
from c_3 in groupAandB
select c_3;
e) Here I’m assuming that answer to d) is that c_3 is indeed bound to a. But when looking at the code into which query_1 is translated at compile time, we could instead argue that c_3 is actually bound to anonymous type a_1 ( ie new { a, groupAandB = os } )?!
groupA.GroupJoin(groupB, a => a, b => b, (a, os) => new { a, groupAandB = os } ).
SelectMany(a_1 => a_1.groupAandB );
f) Keeping in my mind into what query_1 gets translated, couldn’t we argue that any assumptions I made under d) are perhaps conceptually correct, but technically wrong, since at compile time there isn’t any c_3 variable, or perhaps there is c_3 defined somewhere under the hood, but it is actually bound to an anonymous type and not to a?
EDIT:
1)
with Join, the “second” collection can’t depend on which value you’re
currently “looking at” from the first collection,
a) I assume you essentially mean that we can’t join customers to a collection ( ie c.Orders ) returned by current value of c :
var query1 = from c in customers
join o in c.Orders on c.CustomerId equals o.OrderID // this won't work
select new { c.Name, o.OrderID, o.OrderDate };
b) Btw, why is such a join not allowed ( I’m assuming it would be technically feasible to make such a join ) or perhaps why it doesn’t make sense?
2)
“The C# specification gives the explicit transformation involved”
Could you elaborate what you mean by “explicit transformation involved” and how it relates to e) and f) questions?
thank you
Query a gets compiled to:
collection2is enumerated for each element incollection1;collection3is enumerated for every combination of items in the result.If
collection1contains{ 1, 2 },collection2contains{ 11, 12 }, andcollection3contains{ 21, 22 }, then the result will be:Query c gets compiled to:
collection3is enumerated for every combination of items fromcollection1andcollection2which pass the filter.For query d, each
c_3will be the list of items fromgroupBwhich match an element fromgroupA, so if I’ve understood your terminology correctly, it is indeed “bound to”a.