关于对象的 linq,如果我使用 .Where(x => x....) 然后直接使用 .SkipWhile(x => x...) 这会导致性能损失,因为我正在检查收集两次?
我应该找到一种方法将所有内容都放在 Where 子句或 SkipWhile 子句中吗?
关于对象的 linq,如果我使用 .Where(x => x....) 然后直接使用 .SkipWhile(x => x...) 这会导致性能损失,因为我正在检查收集两次?
我应该找到一种方法将所有内容都放在 Where 子句或 SkipWhile 子句中吗?
由于将迭代器链接在一起会导致效率低下,但实际上会非常小。(特别是,虽然两个运算符都会看到每个匹配项,但它们不会被缓冲或类似的东西。LINQ to Object 不会创建所有匹配项的新列表然后运行SkipWhile
它。)
如果这对性能至关重要,那么一开始不使用 LINQ 可能会导致非常轻微的减速。在其他所有情况下,首先编写最简单的代码,只有在证明这是一个瓶颈时才担心这样的微优化。
与大多数事情一样,答案是取决于你在做什么。如果您有多个 where 对同一个对象进行操作,则可能值得将它们与 && 结合起来。
大多数 LINQ 运算符不会遍历每个运算符的整个集合,它们仅处理一个项目并将其传递给下一个运算符。也有例外,例如 Reverse 和 OrderBy,但通常如果您使用 Where 和 SkipWhile,例如,您将拥有一个一次处理一个项目的链。现在你的第一个 Where 语句显然可以过滤掉一些项目,所以 SkipWhile 直到它通过前面的运算符才会看到一个项目。
我个人的偏好是为了清晰起见将操作员分开,只有在性能成为问题时才将它们组合起来。
使用 Where 和 SkipWhile 不会导致“遍历集合两次”。LINQ to Objects 适用于拉模型。当您枚举组合查询时,SkipWhile 将开始向其来源询问元素。它的来源是 Where,因此这将导致 Where 开始依次向其来源询问元素。因此,SkipWhile 将看到所有通过 Where 子句的元素,但它正在获取它们。结果是 LINQ 对原始集合执行了一次 foreach,只返回通过 Where 和 SkipWhile 过滤器的元素——这仅涉及对集合的一次传递。
由于涉及到两个迭代器,因此可能会导致轻微的效率损失,但这不太可能很重要。您应该编写清晰的代码(就像您目前所做的那样),如果您怀疑清晰的版本导致性能问题,请测量以确保,然后才尝试组合子句。
当您使用and时,您不会对集合进行两次检查。Where
SkipWhile
该Where
方法将一次将其输出流式传输到SkipWhile
方法一项,同样,该SkipWhile
方法将一次将其输出流式传输到任何后续方法一项。
(会有一点开销,因为编译器会在后台为每个方法生成单独的迭代器对象。但如果我担心编译器生成的迭代器的开销,那么我可能一开始就不会使用 LINQ。)
不,(基本上)没有性能损失。这就是惰性(延迟)执行的全部意义所在。