LINQ to Objects использует некоторые приемы для оптимизации определенных операций. Например, если вы объедините два оператора .Where
вместе, предикаты будут объединены в один WhereArrayIterator
, поэтому предыдущие могут быть собраны сборщиком мусора. Аналогично, Where
, за которым следует Select
, создаст WhereSelectArrayIterator
, передавая объединенные предикаты в качестве аргумента, так что исходный WhereArrayiterator
можно будет собирать мусором. Таким образом, WhereSelectArrayIterator
отвечает за отслеживание не только selector
, но также и объединенного predicate
, на котором оно может основываться или не основываться.
Поле source
отслеживает только начальный список, который был задан. Из-за предиката результат итерации не всегда будет иметь такое же количество элементов, как source
. Поскольку LINQ предназначен для ленивой оценки, он не должен заранее сравнивать source
с predicate
, чтобы потенциально сэкономить время, если кто-нибудь в итоге вызовет .Count()
. Это может вызвать такой же удар по производительности, как и вызов .ToList()
для него вручную, и если пользователь пропустит его через несколько предложений Where
и Select
, вы в конечном итоге создадите несколько списков без необходимости.
Может ли LINQ to Object быть реорганизован для создания SelectArrayIterator
, который он использует при вызове Select
непосредственно в массиве? Конечно. Будет ли это повысить производительность? Совсем немного. По какой цене? Меньшее повторное использование кода означает дополнительный код для поддержки и тестирования продвижения вперед.
И, таким образом, мы добрались до сути подавляющего большинства вопросов «Почему у языка / платформы X нет функции Y»: с каждой функцией и оптимизацией связана некоторая стоимость, и даже у Microsoft нет неограниченных ресурсов , Как и любая другая компания, они делают оценочные вызовы, чтобы определить, как часто будет выполняться код, который выполняет Select
для массива, а затем вызывает .ToList()
для него, и стоит ли писать этот процесс немного быстрее и ведение другого класса в пакете LINQ.