Вопрос:

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

c# linq

6439 просмотра

3 ответа

75626 Репутация автора

Как я могу написать этот запрос LINQ, используя синтаксис метода расширения?

var query = from a in sequenceA
            from b in sequenceB
            select ...; 
Автор: Olivier Jacot-Descombes Источник Размещён: 02.02.2012 04:09

Ответы (3)


9 плюса

0 Репутация автора

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

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

Автор: user743382 Размещён: 02.02.2012 04:11

46 плюса

570204 Репутация автора

Решение

Для дальнейшего использования на все вопросы этой формы ответит раздел 7.16 спецификации C #.

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


Выражение запроса со вторым 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

Для получения дополнительной информации о прозрачных идентификаторах см. Этот пост от Уэса Дайера, который реализовал их в 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/

Автор: Eric Lippert Размещён: 02.02.2012 05:32

1 плюс

16114 Репутация автора

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

var query = a.Join(b, i => new { }, j => new { }, (i, j) => new { i = i, j = j });
Автор: Bogdan Verbenets Размещён: 30.09.2014 03:56
Вопросы из категории :
32x32