简体   繁体   English

结合LINQ语句以提高效率

[英]Combining LINQ statements for efficiency

regarding linq to objects, if i use a .Where(x => x....) and then straight afterwards use a .SkipWhile(x => x...) does this incur a performance penalty because i am going over the collection twice? 关于linq到对象,如果我使用.Where(x => x ....),然后直接使用.SkipWhile(x => x ...),这会导致性能下降,因为我要检查收集两次?

Should i find a way to put everything in the Where clause or in the SkipWhile clause? 我是否应该找到一种方法将所有内容放在Where子句或SkipWhile子句中?

There will be a minor inefficiency due to chaining iterators together, but it really will be very minor. 由于将迭代器链接在一起,效率会很低,但实际上会非常小。 (In particular, although each matching item will be seen by both operators, they won't be buffered up or anything like that. LINQ to Object isn't going to create a new list of all matching items and then run SkipWhile over it.) (特别是,尽管每个匹配项都将被两个操作员看到,但是它们不会被缓冲或类似的处理。LINQto Object不会创建所有匹配项的新列表, 然后在其上运行SkipWhile 。 )

If this is so performance-critical, you'd probably get a very slight speed bump by not using LINQ in the first place. 如果是这样的性能关键,你可能会在一开始就不使用LINQ得到一个非常轻微的减速。 In every other case, write the simplest code first and only worry about micro-optimisations like this when you've proved it's a bottleneck. 在其他所有情况下,请先编写最简单的代码,并在证明存在瓶颈时才担心像这样的微优化。

As with most things the answer is it depends on what you're doing. 与大多数事情一样,答案取决于您在做什么。 If you have multiple where's the operate on the same object it's probably worth combining them with &&'s for example. 如果您在同一对象上进行多个操作,则可能值得将它们与&&组合在一起。

Most of the LINQ operators won't iterate over the entire collection per operator, they merely process one item and pass it onto the next operator. 大多数LINQ运算符不会迭代每个运算符的整个集合,它们只处理一个项目并将其传递给下一个运算符。 There are exceptions to this such as Reverse and OrderBy, but generally if you were using Where and SkipWhile for example you would have a chain that would process one item at a time. 有一些例外,例如Reverse和OrderBy,但是通常,例如,如果您使用Where和SkipWhile,则您将拥有一条链,一次可处理一项。 Now your first Where statement could obviously filter out some items, so SkipWhile wouldn't see an item until it passed through the preceding operator. 现在,您的第一个Where语句显然可以过滤掉某些项目,因此SkipWhile在通过前一个运算符之前不会看到任何项目。

My personal preference is to keep operators separate for clarity and combine them only if performance becomes an issue. 我个人的喜好是将操作员分开保持清晰,仅在性能成为问题时才将它们合并。

Using a Where and a SkipWhile doesn't result in "going over the collection twice." 使用Where和SkipWhile不会导致“遍历集合两次”。 LINQ to Objects works on a pull model. LINQ to Objects在拉模型上工作。 When you enumerate the combined query, the SkipWhile will start asking its source for elements. 枚举组合查询时,SkipWhile将开始向其来源询问元素。 Its source is the Where, so this will cause the Where to start asking its source in turn for elements. 它的来源是位置,因此这将导致位置开始依次向其来源询问元素。 So the SkipWhile will see all elements that pass the Where clause, but it's getting them as it goes. 因此,SkipWhile将看到所有通过Where子句的元素,但它会随着它们的进行获取。 The upshot is that LINQ does a foreach over the original collection, returning only elements that pass both the Where and SkipWhile filters -- and this involves only a single pass over the collection. 结果是LINQ对原始集合进行了遍历,仅返回同时通过Where和SkipWhile过滤器的元素,而这仅涉及一次对集合的传递。

There may be a trivial loss of efficiency because there are two iterators involved, but it is unlikely to be significant. 由于涉及两个迭代器,因此效率可能会微不足道,但是这不太可能是很重要的。 You should write the code to be clear (as you are doing at the moment), and if you suspect that the clear version is causing a performance issue, measure to make sure , and only then try combining the clauses. 您应该编写清晰的代码(如您目前所做的那样),如果您怀疑清晰的版本导致性能问题,请采取措施确保“” ,然后再尝试合并这些子句。

You aren't going over the collection twice when you use Where and SkipWhile . 当您使用WhereSkipWhile时, 不会对集合进行两次检查。

The Where method will stream its output to the SkipWhile method one item at a time, and likewise the SkipWhile method will stream its output to any subsequent method one item at a time. Where方法将一次将其输出流式传输到SkipWhile方法,同样, SkipWhile方法将一次将其输出流式传输到任何后续方法。

(There will be a small overhead because the compiler generates separate iterator objects for each method behind the scenes. But if I was worried about the overhead of compiler-generated iterators then I probably wouldn't be using LINQ in the first place.) (这会产生少量开销,因为编译器会为幕后的每个方法生成单独的迭代器对象。但是,如果我担心编译器生成的迭代器的开销,那么我可能一开始就不会使用LINQ。)

No, there's (essentially) no performance penalty. 不,(基本上)没有性能损失。 That's what lazy (deferred) execution is all about. 这就是延迟(延迟)执行的全部内容。

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

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