Например .. будет ли первый фильтровать коллекцию ListOfComplexClass, а затем получит свойство StrValue? Или, может быть, произойдет некоторая настройка и сначала выполнение Select, а затем фильтрация возвращенной коллекции?
(я предполагаю, что вы имели в виду p => p.StrValue
в Select
в первом.)
На самом деле, это более тонко, чем это.
Допустим, вы берете перечислитель на первом.
var lst1 = ListOfComplexClass.Where(p => p.StrValue == "Whatever")
.Select(p => p.StrValue);
var e = lst1.GetEnumerator();
Когда вы вызываете e.MoveNext()
, происходит то, что Select
будет вызывать MoveNext()
на итераторе ListOfComplexClass.Where(p => p.StrValue == "Whatever")
, который будет вызывать MoveNext()
итератором ListOfComplexClass
, пока не найдет элемент p
с p.StrValue == "Whatever"
. Затем прогнозируемый результат этого p
будет возвращен как e.Current
.
Теперь давайте рассмотрим второй. Допустим, вы берете его перечислитель.
var lst2 = ListOfComplexClass.Select(p => p.StrValue)
.Where(p => p == "Whatever");
var e = lst2.GetEnumerator();
Когда вы вызываете e.MoveNext()
, Where
будет вызывать MoveNext()
на итераторе ListOfComplexClass.Select(p => p.StrValue)
, пока не найдет элемент p
с p == "Whatever"
. Конечно, вызов MoveNext()
для итератора ListOfComplexClass.Select(p => p.StrValue)
вызовет MoveNext()
для итератора ListOfComplexClass
и вернет проекцию Current
для этого итератора.
У Джона Скита есть хорошая аналогия, которую я здесь украду. Представьте колоду карт в случайном порядке. Представьте себе запросы
var suits = deck.Where(c => c.Suit == Suit.Diamond || c.Suit == Suit.Heart)
.Select(c => c.Suit)
и
var suits = deck.Select(c => c.Suit)
.Where(c => c == Suit.Diamond || c == Suit.Heart);
Теперь представьте, что вы потребляете результат первого запроса. Это идет так.
Select
просит Where
карту.
Where
просит deck
для карты.
*Where
проверяет масть карты.
Если масть карты - бриллиант или сердце, она возвращает карту Select
и Select
проецирует карту в свою масть и возвращает ее.
Если масть карты не алмаз или сердце, Where
запрашивает другую карту из колоды и возвращается к *.
Второй запрос выглядит следующим образом.
Where
просит Select
костюм.
Select
просит deck
для карты.
deck
возвращает карту для выбора.
Select
проецирует карту на свой костюм.
*Where
проверяет костюм от Select
.
Если костюм бриллиант или сердце, Where
возвращает костюм.
Если костюм не бриллиант или сердце, Where
просит Select
другой костюм и возвращается к *.