从“用扩展方法表示的LINQ查询嵌套”

我怎样才能写这个LINQ查询通过使用扩展方法的语法?

var query = from a in sequenceA from b in sequenceB select ...; 

为了将来的参考,这个表单的所有问题都可以通过C#规范的第7.16节回答。

您的具体问题由本段回答:


带有第二个from子句的查询expression式,后跟select子句

 from x1 in e1 from x2 in e2 select v 

被翻译成

 ( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => v ) 

所以你的查询:

 var query = from a in sequenceA from b in sequenceB select ...; 

是相同的

 var query = ( sequenceA ) . SelectMany( a => sequenceB , ( a , b ) => ... ) 

(注意,当然这个假定“…”是一个expression式,而不是一个expression式,后面跟着一个查询延续。)

HDV的答案指出

 var query = ( sequenceA ) . SelectMany( a => ( sequenceB ) . Select( b => ... ) ); 

也将是一个逻辑上有效的翻译,虽然这不是我们实际执行的翻译。 在LINQ实施的早期,这是我们select的翻译。 然而,随着从句的越来越多,使得lambda嵌套越来越深入,给编译器带来了巨大的types推理问题。 这种翻译的select破坏了编译器的性能,所以我们引入了透明的标识符机制,为我们提供了一个更便宜的方法来表示深度嵌套的作用域。

如果这些题目让你感兴趣:

有关为什么深度嵌套的lambdaexpression式给编译器带来难题的更多想法,请参阅:

http://blogs.msdn.com/b/ericlippert/archive/2007/03/26/lambda-expressions-vs-anonymous-methods-part-four.aspx

http://blogs.msdn.com/b/ericlippert/archive/2007/03/28/lambda-expressions-vs-anonymous-methods-part-five.aspx

有关透明标识符的更多信息,请参阅Wes Dyer的这篇文章,他是用C#3.0实现的:

http://blogs.msdn.com/b/wesdyer/archive/2006/12/22/transparent-identifiers.aspx

而我的一系列关于他们的文章:

http://ericlippert.com/2014/07/31/transparent-identifiers-part-one/

 var query = sequenceA.SelectMany(a => sequenceB.Select(b => ...)); 

编辑 :正如Eric Lippert在评论中指出的那样,结果是相同的,但并不是如何在内部翻译的。 查看他的答案,以另一种方式打电话给SelectMany ,这与原来的对应。 另外,为了清楚起见,添加了省略的b =>

另一种写法是:

 var query = a.Join(b, i => new { }, j => new { }, (i, j) => new { i = i, j = j });