Как написать этот запрос LINQ с помощью синтаксиса метода расширения?
var query = from a in sequenceA
from b in sequenceB
select ...;
Как написать этот запрос LINQ с помощью синтаксиса метода расширения?
var query = from a in sequenceA
from b in sequenceB
select ...;
Для вашей будущей ссылки на все вопросы этой формы отвечает раздел 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
, это делает гнездо ягнят все более и более глубоким, что затем представляет компилятор с огромной проблемой в выводе типа. Этот выбор производительности компилятора сокращает количество переводов, поэтому мы внедрили прозрачный механизм идентификатора, чтобы дать нам гораздо более дешевый способ представить морскую среду глубоко вложенных областей.
Если эти предметы вас интересуют:
Дополнительные сведения о том, почему глубоко вложенные лямбды представляют трудную проблему для решения компилятора, см.:
Дополнительные сведения о прозрачных идентификаторах см. в этом сообщении от 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/
var query = sequenceA.SelectMany(a => sequenceB.Select(b => ...));
Изменить: как отметил Эрик Липперт в комментариях, это дает те же результаты, но намеренно не так, как он переведен внутренне. См. Его ответ для другого способа вызвать SelectMany
, который соответствует оригиналу. Кроме того, для ясности добавлен пропущенный b =>
.
Другой способ написать это:
var query = a.Join(b, i => new { }, j => new { }, (i, j) => new { i = i, j = j });