将FROM子句转换为对SelectMany的调用有些困惑

时间:2012-10-24 16:47:54

标签: c# linq linq-to-objects

后续两个 FROM 子句被转换为对SelectMany的调用。

a)

var query = from c_1 in collection_1
            from c_2  in collection_2 
            from c_3 in collection_3
            select ...

如果我错了,请纠正我,但我认为查询表达式被翻译成语义上等同于的代码:

collection_1.SelectMany(c_1 => c_1.collection_2.
               SelectMany(c_2 => c_2.collection_3.
                     Select(c_3 =>  ... )));

from c_3 in collection始终“绑定”到c_2范围变量?使用术语“绑定”我会询问是否为每个collection_3元素枚举了整个c_2

b)假设我在 a) 下是正确的,c_3总是“绑定”到最近定义的范围变量对吗?

c)如果对 b) 的回答为true,则即使在以下示例中c_3也绑定到c_2

var query = from c_1 in collection_1
            from c_2  in collection_2 
            where ...
            from c_3 in collection_3

d)下一个查询c_3是否绑定到a(即每个a将枚举整个groupAandB

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)我假设对 d) 的回答是c_3确实绑定到a。但是当查看在编译时将query_1翻译成的代码时,我们可以反而认为c_3实际上绑定到匿名类型a_1(即new { a, groupAandB = os })?!

groupA.GroupJoin(groupB, a => a, b => b, (a, os) => new { a, groupAandB = os } ).
             SelectMany(a_1 => a_1.groupAandB );

f)在我的脑海中记住query_1被翻译的内容,我们不能认为我在 d) 下做出的任何假设可能在概念上是正确的但在技术上是错误的,因为在编译时没有任何c_3变量,或者可能在某个地方定义了c_3,但它实际上绑定到匿名类型而不是a

修改

1)

  

使用Join,“第二个”集合不能取决于您的值   目前从第一个系列“看”,

a)我假设您基本上是指我们无法将customers加入由当前值c.Orders返回的集合(即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)顺便说一句,为什么不允许这样的连接(我假设在技术上可以进行这样的连接)或者为什么它没有意义呢?

2)

  

“C#规范提供了明确的转换”

您能详细说明“涉及显式转换”的含义以及它与 e) 的关系f) 问题?

谢谢

1 个答案:

答案 0 :(得分:2)

查询get编译为:

collection1
   .SelectMany(c1 => collection2, (c1, c2) => new { c1, c2 })
   .SelectMany(t0 => collection3, (t0, c2) => new { t0.c1, t0.c2, c3 })
;

collection2枚举collection1中的每个元素;对于结果中的每个项目组合,都会枚举collection3

如果collection1包含{ 1, 2 }collection2包含{ 11, 12 }collection3包含{ 21, 22 },则结果将为:

|----|----|----|
| c1 | c2 | c3 |
|----|----|----|
|  1 | 11 | 21 |
|  1 | 11 | 22 |
|  1 | 12 | 21 |
|  1 | 12 | 22 |
|  2 | 11 | 21 |
|  2 | 11 | 22 |
|  2 | 12 | 21 |
|  2 | 12 | 22 |
|----|----|----|

查询c被编译为:

collection1
   .SelectMany(c1 => collection2, (c1, c2) => new { c1, c2 })
   .Where(t0 => ...)
   .SelectMany(t0 => collection3, (t0, c3) => new { t0.c1, t0.c2, c3 })
;
对于通过过滤器的collection3collection1的每个项目组合,都会枚举

collection2

对于查询d,每个c_3都是groupB中与groupA中的元素匹配的项目列表,因此,如果我正确理解您的术语,则确实是“绑定到“a