为了供您将来参考,此表格的所有问题均由 C# 规范第 7.16 节解答。
本段回答了您的具体问题:
带有第二个的查询表达式from
子句后跟一个select
clause
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 ) => ... )
(请注意,当然,这假设“...”是一个表达式,而不是后跟查询继续的表达式。)
hdv 的回答指出
var query = ( sequenceA ) . SelectMany(
a => ( sequenceB ) . Select( b => ... ) );
也将是一个逻辑上有效的翻译,尽管这不是我们实际执行的翻译。在 LINQ 实现的早期,这是我们选择的翻译。然而,当你堆积更多from
子句,它使 lambda 嵌套得越来越深,然后向编译器提供一个enormous类型推断中的问题。这种翻译选择会破坏编译器性能,因此我们引入了透明标识符机制为我们提供了一种更便宜的方式来表示深度嵌套范围的语义。
如果您对这些主题感兴趣:
有关为什么深度嵌套 lambda 给编译器带来难题的更多想法,请参阅:
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/