Недавно я начал использовать LINQ совсем немного, и на самом деле я не видел упоминания о сложности выполнения для любого из методов LINQ. Очевидно, здесь есть много факторов, поэтому позвольте ограничить обсуждение простым провайдером IEnumerable
LINQ to Object. Далее, допустим, что любой Func
, передаваемый в качестве селектора/мутатора/и т.д., Является дешевой операцией O (1).
Кажется очевидным, что все однопроходные операции (Select
, Where
, Count
, Take/Skip
, Any/All
и т.д.) будут O (n), так как им нужно только ходить последовательность один раз; хотя даже это подлежит лени.
Для более сложных операций все более мучительно; (t27 > , Distinct
, Except
и т.д.) работают по умолчанию GetHashCode
(afaik), поэтому представляется разумным предположить, что они используют внутреннюю таблицу хеш-таблиц, делая эти операции O (n), в общем случае. Что относительно версий, которые используют IEqualityComparer
?
OrderBy
понадобится сортировка, поэтому, скорее всего, мы посмотрим на O (n log n). Что, если он уже отсортирован? Как насчет того, если я скажу OrderBy().ThenBy()
и предоставил тот же ключ для обоих?
Я мог видеть GroupBy
(и Join
), используя либо сортировку, либо хеширование. Что он?
Contains
будет O (n) на a List
, но O (1) на a HashSet
- LINQ проверит базовый контейнер, чтобы увидеть, может ли он ускорить процесс?
И реальный вопрос - до сих пор я принимал его на веру, что операции выполнены. Однако могу ли я взять на себя это? Например, контейнеры STL четко определяют сложность каждой операции. Существуют ли аналогичные гарантии производительности LINQ в спецификации библиотеки .NET?
Еще вопрос (в ответ на комментарии):
На самом деле не думал о накладных расходах, но я не ожидал, что там будет очень много для простых Linq-to-Objects. Сообщение CodingHorror говорит о Linq-to-SQL, где я могу понять разбор запроса и заставить SQL добавить стоимость - есть ли аналогичная стоимость для провайдера объектов? Если да, то отличается ли это, если вы используете декларативный или функциональный синтаксис?