Linq - 找出延期执行的最快方法是什么?

时间:2010-10-08 21:38:41

标签: c# .net linq deferred-execution

找出哪些.net框架linq方法(例如.IEnumerable linq方法)使用延迟执行而不是使用延迟执行实现的最快方法是什么。

编码多次,我想知道这个是否会以正确的方式执行。找出答案的唯一方法是访问MSDN文档以确保。会不会有更快捷的方式,任何目录,网络上的任何列表,任何备忘单,你可以分享的任何其他技巧?如果是,请这样做。这将有助于许多linq新手(像我一样)减少错误。唯一的另一个选择是检查文档,直到一个人使用它们足够记住(这对我来说很难,我往往不记得某些地方记录的“任何东西”,可以查找:D)。

6 个答案:

答案 0 :(得分:35)

通常返回序列的方法使用延迟执行:

IEnumerable<X> ---> Select ---> IEnumerable<Y>

和返回单个对象的方法不会:

IEnumerable<X> ---> First ---> Y

因此,WhereSelectTakeSkipGroupByOrderBy等方法会使用延迟执行,因为它们可以FirstSingleToListToArray等方法不会,因为它们不能。

还有两种类型的延迟执行。例如,Select方法只会在要求生成项目时获得一个项目,而OrderBy方法在被要求返回第一个项目时必须使用整个源项目。因此,如果您在OrderBy之后链接Select,则执行将推迟到您获得第一个项目,但OrderBy将询问Select所有项目

答案 1 :(得分:8)

我使用的指南:

  • 始终假设任何返回IEnumerable<T>IQueryable<T>的API都可以并且可能会使用延迟执行。如果您正在使用这样的API,并且需要多次迭代结果(例如,获取Count),那么在执行此操作之前转换为集合(通常通过调用.ToList()扩展方法。

  • 如果您正在公开枚举,请始终将其公开为集合(ICollection<T>IList<T>),如果这是您的客户通常会使用的。例如,数据访问层通常会返回域对象的集合。如果延迟执行是您正在公开的API的合理选项,则仅公开IEnumerable<T>

答案 2 :(得分:5)

实际上,还有更多;此外,您需要考虑缓冲与非缓冲。 OrderBy可以延迟,但迭代时 必须使用整个流。

通常,返回IEnumerable 的LINQ中的任何内容都会延迟 - 而Min等(返回值)不会延迟。缓冲(vs not)通常可以被推理,但坦率地说反射器是一种非常快速的方法来确定。但请注意,这通常是一个实现细节。

答案 3 :(得分:2)

对于实际的“延迟执行”,您需要适用于IQueryable的方法。基于IQueryable工作的方法链,用于构建表示查询的表达式树。只有当你调用一个接受IQueryable并产生具体或IEnumerable结果的方法(ToList()和类似的,AsEnumerable()等)时,Linq提供者才会评估它(Linq2Objects内置于Framework中,Linq2SQL和现在MSEF;其他ORM和持久层框架也提供Linq提供者)并返回实际结果。可以使用AsQueryable()扩展方法将框架中的任何IEnumerable类强制转换为IQueryable,并且将转换表达式树的Linq提供程序(如ORM)将提供AsQueryable()作为linq查询的跳转点。他们的数据。

即使针对IEnumerable,一些Linq方法也是“懒惰的”。因为IEnumerable的优点在于您不必了解所有内容,只有当前元素以及是否有另一个,作用于IEnumerable的Linq方法通常返回一个迭代器类,每当从源中吐出一个对象时后来在链中的方法要求一个。任何不需要了解整个集合的操作都可以进行延迟评估(选择和哪里有两个大的;还有其他的)。确实需要了解整个集合(通过OrderBy进行排序,使用GroupBy进行分类以及像Min和Max这样的聚合)将会将其整个源可以插入到List或Array中并对其进行处理,从而强制通过所有更高节点评估所有元素。一般来说,如果你能帮助它们,你希望这些在方法链中来得晚。

答案 4 :(得分:2)

以下是您可以了解是否推迟查询的多种方式的摘要:

  1. 如果您使用查询表达式语法而不是查询方法语法,则将其推迟。

  2. 如果您使用的是查询方法语法,则可能会根据其返回的内容来推迟它。

  3. 将鼠标悬停在关键字var上(如果这就是您用来存储查询的变量的类型)。如果显示IEnumerable<T>,则将其推迟。

  4. 尝试使用foreach遍历查询。如果您收到一条错误消息,说它由于不支持GetEnumerator()而不能遍历变量,那么您就知道查询不会被推迟。

来源:Essential Linq

答案 5 :(得分:1)

如果使用.AsQueryable()将集合强制转换为IQueryable,则LINQ调用将使用延迟执行。

见这里:Using IQueryable with Linq