Nested “from” LINQ query expressed with extension methods

后端 未结 3 863
轻奢々
轻奢々 2020-11-27 17:35

How can I write this LINQ query by using the extension method syntax?

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


        
相关标签:
3条回答
  • 2020-11-27 18:01
    var query = sequenceA.SelectMany(a => sequenceB.Select(b => ...));
    

    Edit: as pointed out by Eric Lippert in the comments, this gives the same results, but is intentionally not how it is translated internally. See his answer for another way to call SelectMany, which does correspond to the original. Also, added the omitted b => for clarity.

    0 讨论(0)
  • 2020-11-27 18:01

    Another way to write it would be:

    var query = a.Join(b, i => new { }, j => new { }, (i, j) => new { i = i, j = j });
    
    0 讨论(0)
  • 2020-11-27 18:13

    For your future reference, all questions of this form are answered by section 7.16 of the C# specification.

    Your specific question is answered by this paragraph:


    A query expression with a second from clause followed by a select clause

    from x1 in e1
    from x2 in e2
    select v
    

    is translated into

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

    So your query:

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

    Is the same as

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

    (Note that of course this assumes that the "..." is an expression, and not, say, an expression followed by a query continuation.)

    hdv's answer points out that

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

    would also be a logically valid translation, though it is not the translation we actually perform. In the early days of LINQ implementation, this was the translation we chose. However, as you pile on more from clauses, it makes the lambdas nest more and more deeply, which then presents the compiler with an enormous problem in type inference. This choice of translation wrecks compiler performance, so we introduced the transparent identifier mechanism to give us a much cheaper way to represent the seamntics of deeply nested scopes.

    If these subjects interest you:

    For more thoughts on why deeply nested lambdas present a hard problem for the compiler to solve, see:

    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

    For more information about transparent identifiers, see this post from Wes Dyer, who implemented them in C# 3.0:

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

    And my series of articles about them:

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

    0 讨论(0)
提交回复
热议问题