Практические правила для того, когда вызывать ToList при возврате результатов LINQ - PullRequest
10 голосов
/ 30 июля 2010

Я ищу практические правила для вызова ToList/ToArray/MemoizeAll(Rx) на IEnumerables, в отличие от возврата самого запроса при возврате IEnumerable чего-либо.

Часто я нахожу, что лучше просто вернуть запрос и позволить вызывающему абоненту решить, нужен ли список, или нет, но иногда он может вернуться и укусить вас сзади из-за ленивой природы linq.

Я хочу собрать рекомендации, такие как:

Call ToList, если:

  • вы создаете новые объекты (например, в выборке)
  • у вас есть побочные эффекты в вашем запросе

В противном случае вернуть запрос

Ответы [ 5 ]

23 голосов
/ 30 июля 2010

Во-первых, вы никогда не должны иметь побочных эффектов в запросе. Это худшая практика. Запросы должны отвечать на вопрос, а не давать эффект.

Ответ на ваш вопрос: вернуть запрос, когда вызывающий ожидает запрос; вернуть список, когда вызывающий ожидает список. Когда вы разрабатываете свой метод, решите, что с большей вероятностью понадобится вызывающей стороне, реализуйте это, а затем document it.

При рассмотрении вопроса о том, хочет ли вызывающий запрос запрос или список, подумайте о различиях между запросами и списками:

  • запросов всегда актуальны. Если объекты / базы данных / все, что запрашивает запрос, изменяет его содержимое, то результаты запроса изменятся, если вы снова запустите запрос. Списки не меняют своего содержимого, поэтому списки устаревают . Если вашему абоненту требуются самые последние данные , отправьте ему запрос. Если им требуется снимок данных, которые они могут просмотреть в свободное время , предоставьте им список.

  • запросов потенциально дорого выполнять для получения своих результатов. Списки дешевы, чтобы получить их результаты. Если вызывающий абонент, скорее всего, захочет запросить результат много раз и ожидает, что каждый раз получит одинаковые результаты, предоставьте им список.

  • Построение запроса: fast . Выполнение запроса для построения списка: медленно . Список всегда получает все результаты запроса. Вызывающий может захотеть дополнительно ограничить запрос, скажем, взяв только первые десять элементов. Если вызывающая сторона не хочет или нуждается в полной итерации по всему запросу, тогда дайте им запрос; не принимайте это решение от их имени и не предоставьте им список.

  • запросов крошечные . Списки большие . Многие запросы могут быть повторены по n элементам в пространстве O (1); список из n элементов занимает O (n) места. Если результирующий набор огромен, то помещение его в список, вероятно, неэффективно.

  • и так далее.

Нет простого ответа. Ответ совпадает с ответом на любую другую проблему проектирования: Рассмотрите все плюсы и минусы каждого возможного решения в контексте того, что наиболее вероятно требуется пользователю функции, а затем выберите разумное компромиссное решение. .

3 голосов
/ 30 июля 2010

Возврат ToList, если:

  • Вы не хотите или не хотите обрабатывать ленивые запросы.

Edit:

Кроме того, вернуть ToList, если:

  • Вы используете какую-то инфраструктуру Linq to SQL (LLBLGen, EF и т. Д.), И вам необходимо выполнить операцию со списком, которую среда не может преобразовать в SQL.
2 голосов
/ 30 июля 2010

Используйте ToList перед выходом из блока using, который содержит ваш DataContext.

Возвращает запрос, когда вызывающая сторона, вероятно, / обязана предоставить дополнительные критерии фильтрации, которые будут использоваться индексами для уменьшения числа строк результатов и / или ввода-вывода базы данных.

2 голосов
/ 30 июля 2010

Используйте ToList, если вам нужно запускать пользовательские функции для данных, возвращаемых LINQ to SQL.

1 голос
/ 30 июля 2010

вы ToList(), когда вы хотите список объектов для вашего результата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...