【问题标题】:FindAll Vs Where [duplicate]FindAll Vs Where [重复]
【发布时间】:2016-01-09 16:45:39
【问题描述】:

我有一个 IEnumerable<T>,我想根据 LINQ 谓词进行过滤。我尝试像往常一样在IEnumerable 上使用Where,但这次我偶然发现了一些有趣的东西。当使用谓词在 IEnumerable 上调用 Where 时,我得到一个空列表作为回报。我知道它必须生成一个包含两个项目的列表。如果我改用 FindAll 和相同的谓词,它会产生正确的结果。

谁能给我解释一下,为什么会这样?我一直认为WhereFindAll 的懒惰版本,它也返回IEnumerable 而不是List。应该不止这些吧? (我做了一些研究,但无济于事。)

代码:

IEnumerable<View> views = currentProject.Views.Where(
                    v => v.Entries.Any(e => e.Type == InputType.IMAGE || e.Type == InputType.VIDEO));

IEnumerable<View> views = currentProject.Views.FindAll(
                    v => v.Entries.Any(e => e.Type == InputType.IMAGE || e.Type == InputType.VIDEO));

【问题讨论】:

  • List&lt;T&gt;.FindAll 返回 List&lt;T&gt;Where 返回 IEnumerable&lt;T&gt;。但是Where 使用的是延迟执行,所以只有当你 materialize 它时你才能得到它,f.e. ToList.
  • 您为什么不将其发布为答案? :) 比这里唯一的答案更好的解释,比您的评论晚发布。
  • 即使您的评论回答了问题,但已经发布了一个答案,该答案比链接问题的任何答案都更彻底。
  • 我知道:)

标签: c# .net linq list ienumerable


【解决方案1】:

您可以在这里找到答案:LINQ, Where() vs FindAll()。基本上,如果您在“Where”上调用 .ToList(),它们将是相同的。

您可以找到有关延迟执行和立即执行之间区别的更多信息:https://code.msdn.microsoft.com/LINQ-Query-Execution-ce0d3b95

【讨论】:

  • 我知道您所说的可能是对两者之间差异的简化解释,但我明白了。谢谢!
【解决方案2】:

我最好的猜测是在调用 Where 之间发生了一些事情,它创建了一个枚举器和代码中实际使用结果的位置(即实际调用该枚举器的 MoveNext 和 (get_)Current 的位置,例如从 ToList )。

【讨论】:

  • 这里的问题是,我在 IEnumerable 上使用 Where() 时没有调用 .ToList(),因此检查它显示了一个空列表。
【解决方案3】:

是的,findall 的懒惰版本在哪里。 FindAll() 是 List 类型的函数,它不是像 Where 那样的 LINQ 扩展方法。 List 上的 FindAll 方法,它是返回具有相同元素类型的新 List 的实例方法。 FindAll 只能用于 List 实例,而 LINQ 扩展方法适用于任何实现 IEnumerable 的类型。

主要区别(除了它们的实现方式:IEnumerable 与 List)是 Where 实现了延迟执行,在您需要它之前它实际上不会进行查找,(例如在 foreach 循环中使用它)。 FindAll 是立即执行方法。

我将参考一种称为表达式树的数据结构来理解延迟执行,您只需了解表达式树是一种类似于列表或队列的数据结构。它保存一个 LINQ to SQL 查询,不是查询的结果,而是查询本身的实际元素。

要了解Where的工作方式,我们需要看看如果我们编写代码

var query = from customer in db.Customers  
        where customer.City == "Paris"
        select customer;              

查询不在此处执行,而在 foreach 循环中执行

了解LINQ and Deferred Execution

【讨论】:

    猜你喜欢
    • 2011-01-16
    • 2010-12-04
    • 2013-04-15
    • 1970-01-01
    • 2017-11-29
    • 2015-10-31
    • 2016-11-05
    • 2020-04-04
    • 1970-01-01
    相关资源
    最近更新 更多