简体   繁体   English

AsEnumerable()是否缓存所有结果(LINQ)

[英]Does AsEnumerable() cache all result (LINQ)

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. 我的意思是,如果我在IEnumerable<>上调用Where<>()运算符,将在Enumerable类中定义将被调用的运算符,如果在IQueryable<>对其进行调用,则将调用Queryable类中定义的那个运算符。

Consider the operator Reverse, defined in the Enumerable class. 考虑在Enumerable类中定义的Reverse运算符。
If i want to call it on Iqueryable<> then I must use the AsEnumerable<>() operator to first convert it into IEnumerable<> . 如果我想在Iqueryable<>上调用它,则必须使用AsEnumerable<>()运算符首先将其转换为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. 但是Reverse运算符必须同时拥有所有记录,以便可以将它们反转。
In the above code do all the records get loaded in memory first and then the Reverse() operator is reversing it ? 在上面的代码中,是否所有记录都首先加载到内存中,然后Reverse()运算符将其反转?

AsEnumerable does nothing other than change the compile-time type of the expression. AsEnumerable除了更改表达式的编译时类型外,什么也不做。

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. 唯一的一点是更改编译时类型,以强制使用Enumerable扩展方法而不是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. IIRC,LINQ to SQL实际上会将所有内容加载到内存中-但我可能是错的。 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; 当然, Reverse无论如何都会缓冲任何东西,但这并不意味着它将使用双倍的内存-在大多数情况下,这仅意味着它将缓冲对对象的引用 it doesn't create a new copy of each object. 它不会为每个对象创建一个新副本。

IQueryable<T> extends IEnumerable<T> , so the AsEnumerable is redundant. IQueryable<T>扩展了IEnumerable<T> ,因此AsEnumerable是冗余的。 However, if you use it, AsEnumerable is not going to greedily load the collection (that would be a very annoying "feature"). 但是,如果使用它,AsEnumerable将不会贪婪地加载集合(那将是一个非常烦人的“功能”)。 Clearly, Reverse will need the whole thing. 显然,反向将需要整个过程。 Mono implements Enumerable.Reverse using a List<T> and a simple iterator-generator that yields in reverse. Mono使用List<T>和一个简单的迭代器生成器实现Enumerable.Reverse ,反向生成。

I believe the only real purpose of AsEnumerable is to force the use of IEnumerable explicit interface implementations. 我相信AsEnumerable的唯一真正目的是强制使用IEnumerable显式接口实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM