Does AsEnumerable() cache all result (LINQ)

2019-08-23 10:11发布

When we call a query operator on a sequence, a sequence-specific operator gets called.
I mean if i call Where<>() operator on IEnumerable<>, the operator that will be called will be defined in Enumerable class and if it's called on IQueryable<>, the one defined in Queryable class will be called.

Consider the operator Reverse, defined in the Enumerable class.
If i want to call it on Iqueryable<> then I must use the AsEnumerable<>() operator to first convert it into IEnumerable<>.

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

But the Reverse operator got to have all records at the same time so that it can reverse them.
In the above code do all the records get loaded in memory first and then the Reverse() operator is reversing it ?

2条回答
smile是对你的礼貌
2楼-- · 2019-08-23 10:26

IQueryable<T> extends IEnumerable<T>, so the AsEnumerable is redundant. However, if you use it, AsEnumerable is not going to greedily load the collection (that would be a very annoying "feature"). Clearly, Reverse will need the whole thing. Mono implements Enumerable.Reverse using a List<T> and a simple iterator-generator that yields in reverse.

I believe the only real purpose of AsEnumerable is to force the use of IEnumerable explicit interface implementations.

查看更多
贪生不怕死
3楼-- · 2019-08-23 10:38

AsEnumerable does nothing other than change the compile-time type of the expression.

It's implemented like this:

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

It doesn't even check for nullity!

The only point is to change the compile-time type, to force the rest of the query to be executed with the Enumerable extension methods instead of Queryable. It's like a cast - except a cast would often be inconvenient in the middle of a query, and for anonymous types you wouldn't be able to cast it anyway.

So, it's really about what the "source" of the query does when it's enumerated. Does that source load everything into memory before returning any results, or does it stream them? IIRC, LINQ to SQL will actually load everything into memory - but I could be wrong. Of course Reverse is going to buffer anything anyway, but that doesn't mean it'll use double the memory - in most cases that only means it will buffer references to objects; it doesn't create a new copy of each object.

查看更多
登录 后发表回答