Сохраняет ли AsEnumerable () весь результат (LINQ) - PullRequest
0 голосов
/ 24 мая 2010

Когда мы вызываем оператор запроса для последовательности, вызывается оператор, специфичный для последовательности.
Я имею в виду, если я вызову оператор Where<>() для IEnumerable<>, оператор, который будет вызван, будет определен в классе Enumerable, а если он будет вызван в IQueryable<>, будет вызван оператор, определенный в классе Queryable.

Рассмотрим оператор Reverse, определенный в классе Enumerable.
Если я хочу вызвать его на Iqueryable<>, тогда я должен использовать оператор AsEnumerable<>(), чтобы сначала преобразовать его в IEnumerable<>.

db.Countries.OrderBy(cntry=>cntry.CountryName).AsEnumerable().Reverse()

Но оператор Reverse должен иметь все записи одновременно, чтобы он мог их отменить.
В приведенном выше коде все записи сначала загружаются в память, а затем оператор Reverse () обращает их вспять?

Ответы [ 2 ]

4 голосов
/ 24 мая 2010

AsEnumerable не делает ничего, кроме изменения типа выражения во время компиляции.

Это реализовано так:

public static IEnumerable<T> AsEnumerable<T>(this IEnumerable<T> source)
{
    return source;
}

Он даже не проверяет на ничтожность!

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

Итак, на самом деле речь идет о том, что делает «источник» запроса при его перечислении. Загружает ли этот источник все данные в память перед возвратом каких-либо результатов или передает их в потоковом режиме? IIRC, LINQ to SQL фактически загрузит все в память - но я могу ошибаться. Конечно, Reverse в любом случае собирается что-то буферизовать, но это не значит, что он будет использовать двойную память - в большинстве случаев это означает, что он будет ссылаться на объекты *1012*; он не создает новую копию каждого объекта.

1 голос
/ 24 мая 2010

IQueryable<T> расширяет IEnumerable<T>, поэтому AsEnumerable является избыточным.Однако, если вы используете его, AsEnumerable не будет жадно загружать коллекцию (это было бы очень раздражающей «функцией»).Понятно, что Реверсу понадобится все это.Mono реализует Enumerable.Reverse , используя List<T> и простой итератор-генератор, который возвращает в обратном порядке.

Я считаю, что единственная реальная цель AsEnumerable - принудительно использовать явный интерфейс IEnumerableреализации.

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