Подтвердить что ты не робот

Вложенный "из" запроса LINQ, выраженный с помощью методов расширения

Как написать этот запрос LINQ с помощью синтаксиса метода расширения?

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

Ответ 1

Для вашей будущей ссылки на все вопросы этой формы отвечает раздел 7.16 спецификации С#.

На ваш конкретный вопрос отвечает этот параграф:


Выражение запроса со вторым предложением from, за которым следует предложение 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 ) => ... )

(Обратите внимание, что, конечно, это предполагает, что "..." является выражением, а не, скажем, выражением, сопровождаемым продолжением запроса.)

Ответ hdv указывает, что

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

также будет логически корректным переводом, хотя это не перевод, который мы фактически выполняем. В первые дни реализации LINQ это был перевод, который мы выбрали. Однако, поскольку вы накладываете больше на предложения from, это делает гнездо ягнят все более и более глубоким, что затем представляет компилятор с огромной проблемой в выводе типа. Этот выбор производительности компилятора сокращает количество переводов, поэтому мы внедрили прозрачный механизм идентификатора, чтобы дать нам гораздо более дешевый способ представить морскую среду глубоко вложенных областей.

Если эти предметы вас интересуют:

Дополнительные сведения о том, почему глубоко вложенные лямбды представляют трудную проблему для решения компилятора, см.:

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, который реализовал их в С# 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/

Ответ 2

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

Изменить: как отметил Эрик Липперт в комментариях, это дает те же результаты, но намеренно не так, как он переведен внутренне. См. Его ответ для другого способа вызвать SelectMany, который соответствует оригиналу. Кроме того, для ясности добавлен пропущенный b =>.

Ответ 3

Другой способ написать это:

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