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

发布于 2024-09-27 09:00:46 字数 290 浏览 7 评论 0原文

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

在多次编码时,我想知道这一次是否会以正确的方式执行。找到答案的唯一方法是访问 MSDN 文档进行确认。是否有任何更快的方法,任何目录,网络上某个地方的任何列表,任何备忘单,任何其他可以分享的技巧?如果是,请这样做。这将帮助许多 linq 菜鸟(比如我)减少犯错误。唯一的其他选择是检查文档,直到人们使用它们足以记住(这对我来说很难,我倾向于不记得记录在某处并且可以查找的“任何内容”:D)。

What is the quickest way to find out which .net framework linq methods (e.g .IEnumerable linq methods) are implemented using deferred execution vs. which are not implemented using deferred execution.

While coding many times, I wonder if this one will be executed right way. The only way to find out is go to MSDN documentation to make sure. Would there be any quicker way, any directory, any list somewhere on the web, any cheat sheet, any other trick up your sleeve that you can share? If yes, please do so. This will help many linq noobs (like me) to make fewer mistakes. The only other option is to check documentation until one have used them enough to remember (which is hard for me, I tend not to remember "anything" which is documented somewhere and can be looked up :D).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

野鹿林 2024-10-04 09:00:46

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

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

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

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

因此,像 WhereSelectTakeSkipGroupByOrderBy 使用延迟执行,因为它们可以,而像 First这样的方法SingleToListToArray 不会,因为它们不能。

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

Generally methods that return a sequence use deferred execution:

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

and methods that return a single object doesn't:

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

So, methods like Where, Select, Take, Skip, GroupBy and OrderBy use deferred execution because they can, while methods like First, Single, ToList and ToArray don't because they can't.

There are also two types of deferred execution. For example the Select method will only get one item at a time when it's asked to produce an item, while the OrderBy method will have to consume the entire source when asked to return the first item. So, if you chain an OrderBy after a Select, the execution will be deferred until you get the first item, but then the OrderBy will ask the Select for all the items.

七月上 2024-10-04 09:00:46

我使用的准则:

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

  • 如果要公开枚举,请始终将其公开为集合(ICollectionIList)(如果您的客户端通常使用该集合),例如,数据访问层通常会返回以下集合。仅当延迟执行对于您所公开的 API 来说是一个合理的选项时,才公开 IEnumerable

The guidelines I use:

  • Always assume any API that returns IEnumerable<T> or IQueryable<T> can and probably will use deferred execution. If you're consuming such an API, and need to iterate through the results more than once (e.g. to get a Count), then convert to a collection before doing so (usually by calling the .ToList() extension method.

  • If you're exposing an enumeration, always expose it as a collection (ICollection<T> or IList<T>) if that is what your clients will normally use. For example, a data access layer will often return a collection of domain objects. Only expose IEnumerable<T> if deferred execution is a reasonable option for the API you're exposing.

猫九 2024-10-04 09:00:46

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

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

Actually, there's more; in addition you need to consider buffered vs non-buffered. OrderBy can be deferred, but when iterated must consume the entire stream.

In general, anything in LINQ that returns IEnumerable tends to be deferred - while Min etc (which return values) are not deferred. The buffering (vs not) can usually be reasoned, but frankly reflector is a pretty quick way of finding out for sure. But note that often this is an implementation detail anyway.

深海夜未眠 2024-10-04 09:00:46

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

即使针对 IEnumerable,某些 Linq 方法也是“惰性的”。因为 IEnumerable 的优点在于您不必了解所有内容,只需了解当前元素以及是否存在另一个元素,因此作用于 IEnumerable 的 Linq 方法通常会返回一个迭代器类,该迭代器类在任何时候都会从其源中吐出一个对象链中稍后的方法需要一个。任何不需要了解整个集合的操作都可以进行延迟评估(Select 和Where 是两个大的操作;还有其他操作)。那些确实需要知道整个集合的集合(通过 OrderBy 排序、使用 GroupBy 分组以及像 Min 和 Max 这样的聚合)会将其整个源可枚举到 List 或 Array 中并对其进行处理,强制通过所有更高的节点评估所有元素。一般来说,如果可以的话,您希望这些在方法链中较晚出现。

For actual "deferred execution", you want methods that work on an IQueryable. Method chains based on an IQueryable work to build an expression tree representing your query. Only when you call a method that takes the IQueryable and produces a concrete or IEnumerable result (ToList() and similar, AsEnumerable(), etc) is the tree evaluated by the Linq provider (Linq2Objects is built into the Framework, as is Linq2SQL and now the MSEF; other ORMs and persistence-layer frameworks also offer Linq providers) and the actual result returned. Any IEnumerable class in the framework can be cast to an IQueryable using the AsQueryable() extension method, and Linq providers that will translate the expression tree, like ORMs, will provide an AsQueryable() as a jump-off point for a linq query against their data.

Even against an IEnumerable, some of the Linq methods are "lazy". Because the beauty of an IEnumerable is that you don't have to know about all of it, only the current element and whether there's another, Linq methods that act on an IEnumerable often return an iterator class that spits out an object from its source whenever methods later in the chain ask for one. Any operation that doesn't require knowledge of the entire set can be lazily evaluated (Select and Where are two big ones; there are others). Ones that do require knowing the entire collection (sorting via OrderBy, grouping with GroupBy, and aggregates like Min and Max) will slurp their entire source enumerable into a List or Array and work on it, forcing evaluation of all elements through all higher nodes. Generally, you want these to come late in a method chain if you can help it.

花开浅夏 2024-10-04 09:00:46

以下是您可以了解查询是否会延迟的不同方法的摘要:

  1. 如果您使用查询表达式语法而不是查询方法语法,那么查询将会延迟。

  2. 如果您使用查询方法语法,则可能会根据其返回的内容进行延迟。

  3. 将鼠标悬停在 var 关键字上(如果您使用该关键字作为用于存储查询的变量的类型)。如果显示 IEnumerable,那么它将被推迟。

  4. 尝试使用 foreach 迭代查询。如果您收到一条错误消息,指出它无法迭代您的变量,因为它不支持 GetEnumerator(),您就知道查询没有延迟。

来源:Essential Linq

Here's a summary of different ways you can know if your query will be deferred or not:

  1. If you're using query expression syntax instead of query method syntax, then it will be deferred.

  2. If you're using query method syntax, it MIGHT be deferred depending on what it returns.

  3. Hover over the var key word (if that's what you're using as the type for the variable used to store the query). If it says IEnumerable<T> then it'll be deferred.

  4. Try to iterate over the query using a foreach. If you get an error saying it cannot iterate over your variable because it does not support GetEnumerator(), you know the query is not deferred.

Source: Essential Linq

雨的味道风的声音 2024-10-04 09:00:46

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

请参阅此处:将 IQueryable 与 Linq 结合使用

If you cast the collection to an IQueryable using .AsQueryable(), your LINQ calls will use the deferred execution.

See here: Using IQueryable with Linq

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文