Почему ToLookup и GroupBy отличаются?

.ToLookup<TSource, TKey> возвращает ILookup<TKey, TSource>. ILookup<TKey, TSource> также реализует интерфейс IEnumerable<IGrouping<TKey, TSource>>.

.GroupBy<TSource, TKey> возвращает IEnumerable<IGrouping<TKey, TSource>>.

ILookup имеет удобное свойство индексатора, поэтому его можно использовать в стиле, подобном словарю (или похожим на поиск), тогда как GroupBy не может. GroupBy без индексатора - это боль для работы; в значительной степени единственный способ, которым вы можете ссылаться на возвращаемый объект, - это перебирать его (или использовать другой метод расширения LINQ). Другими словами, в любом случае, который работает GroupBy, ToLookup также будет работать.

Все это оставляет мне вопрос, почему я буду беспокоиться о GroupBy? Почему он должен существовать?

Ответ 1

почему я буду беспокоиться о GroupBy? Почему он должен существовать?

Что происходит, когда вы вызываете ToLookup на объект, представляющий таблицу удаленной базы данных с миллиардом строк?

Минуты строк отправляются по проводу, и вы создаете таблицу поиска локально.

Что происходит, когда вы вызываете GroupBy на такой объект?

Создается объект запроса; конец истории.

Когда этот объект запроса перечислит, анализ таблицы выполняется на сервере базы данных, и сгруппированные результаты отправляются обратно по требованию несколько раз.

Логически это одно и то же, но последствия каждого из них совершенно разные. Вызов ToLookup означает, что я хочу, чтобы кеш всей вещи теперь организован группой. Вызов GroupBy означает "Я создаю объект для представления вопроса", как бы выглядели эти вещи, если бы я организовал их по группе? "

Ответ 2

В простых словах LINQ:

  • ToLookup() - немедленное выполнение
  • GroupBy() - отсроченное исполнение

Ответ 3

Оба схожи, но используются в разных сценариях. .ToLookup() возвращает готовый к использованию объект, у которого уже есть все группы (но не содержимое группы), которые с нетерпением загружены. С другой стороны, .GroupBy() возвращает ленивую загруженную последовательность групп.

Различные поставщики LINQ могут иметь разные типы поведения для нетерпеливой и ленивой загрузки групп. С LINQ-to-Object это, вероятно, мало чем отличается, но с LINQ-to-SQL (или LINQ-to-EF и т.д.) Операция группировки выполняется на сервере базы данных, а не на клиенте, и поэтому вы можете захотеть для дополнительной фильтрации на групповом ключе (который генерирует предложение HAVING), а затем получает только некоторые из групп, а не все из них. .ToLookup() не допускает такой семантики, поскольку все элементы сгруппированы с нетерпением.