Когда форсировать оценку запроса LINQ? - PullRequest
3 голосов
/ 24 сентября 2011

Какова общепринятая практика принудительного вычисления запросов LINQ с помощью таких методов, как ToArray(), и существует ли общая эвристика для составления оптимальных цепочек запросов? Я часто пытаюсь сделать все за один проход, потому что в этих случаях я заметил, что AsParallel() действительно хорошо справляется с задачей ускорения вычислений. В тех случаях, когда запросы выполняют вычисления без побочных эффектов, но для получения правильных данных требуется несколько проходов, форсировать вычисления с помощью ToArray() - правильный путь или лучше оставить запрос в ленивой форме?

Ответы [ 3 ]

3 голосов
/ 24 сентября 2011

Если вы не против использования «экспериментальной» библиотеки, вы можете использовать метод расширения EnumerableEx.Memoize из библиотеки Interactive Extensions .

Этот метод обеспечивает лучший из-both-worlds опция, где базовая последовательность вычисляется по требованию, но не пересчитывается при последующих проходах.Другое небольшое преимущество, на мой взгляд, заключается в том, что тип возвращаемого значения не является изменяемой коллекцией, как это было бы с ToArray или ToList.

2 голосов
/ 24 сентября 2011

Храните запросы в ленивой форме, пока не начнете оценивать запрос несколько раз, или даже раньше, если они вам понадобятся в другой форме или . Вы рискуете получить переменные, захваченные в замыканиях, которые изменят свои значения.1003 *

Возможно, вы захотите оценить , когда запрос содержит сложные проекции, которые вы хотите избежать многократного выполнения (например, построение сложных объектов для последовательностей с большим количеством элементов).В этом случае оценка один раз и многократная итерация намного разумнее.

Вам могут понадобиться результаты в другой форме , если вы хотите вернуть их или передать их другому API, который ожидает определенный типof collection.

Возможно, вы захотите или должны запретить доступ к измененным замыканиям , если запрос захватывает переменные, которые не являются локальными в области.Пока запрос на самом деле не оценен, вы рискуете, что другой код изменит свои значения «за вашей спиной»;когда происходит оценка, он будет использовать эти значения вместо тех, которые присутствовали при создании запроса. (Однако это можно обойти, скопировав эти значения в другую переменную, имеющую локальную область видимости).

1 голос
/ 24 сентября 2011

Обычно вы используете ToArray() только тогда, когда вам нужно использовать массив, как с API, который ожидает массив.Если вам не нужен доступ к результатам запроса и вы не ограничены каким-либо контекстом соединения (например, в случае LINQ to SQL или LINQ to Entities), вы можете простодержите запрос в ленивом виде.

...