Anidado “de” consulta LINQ expresada con métodos de extensión

¿Cómo puedo escribir esta consulta LINQ utilizando la syntax del método de extensión?

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

Para su futura referencia, todas las preguntas de este formulario son respondidas por la sección 7.16 de la especificación C #.

Su pregunta específica es respondida por este párrafo:


Una expresión de consulta con una segunda cláusula from seguida de una cláusula select

 from x1 in e1 from x2 in e2 select v 

se traduce a

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

Entonces tu consulta:

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

Es lo mismo que

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

(Tenga en cuenta que, por supuesto, esto supone que el “…” es una expresión, y no, por ejemplo, una expresión seguida de una consulta de continuación).

La respuesta de hdv señala que

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

también sería una traducción lógicamente válida, aunque no es la traducción que realmente realizamos. En los primeros días de la implementación de LINQ, esta era la traducción que elegimos. Sin embargo, a medida que agregas más cláusulas, hace que las lambdas aniden más y más profundamente, lo que luego presenta al comstackdor un enorme problema en la inferencia de tipos. Esta elección de traducción arruina el rendimiento del comstackdor, por lo que presentamos el mecanismo de identificador transparente para proporcionarnos una forma mucho más económica de representar la senamntica de los ámbitos profundamente nesteds.

Si estos temas te interesan:

Para más ideas sobre por qué las lambdas profundamente anidadas presentan un problema difícil de resolver para el comstackdor, ver:

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

Para obtener más información sobre los identificadores transparentes, consulte esta publicación de Wes Dyer, quien los implementó en C # 3.0:

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

Y mi serie de artículos sobre ellos:

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

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

Editar : como señaló Eric Lippert en los comentarios, esto da los mismos resultados, pero intencionalmente no es la forma en que se traduce internamente. Vea su respuesta para otra forma de llamar a SelectMany , que corresponde al original. Además, se agregó el omitido b => para mayor claridad.

Otra forma de escribirlo sería:

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