FindAll 与 Where

FindAll Vs Where

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

谁能给我解释一下,为什么会这样?我一直认为 WhereFindAll 的懒惰版本,它还 return 编辑了 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));

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

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

我最好的猜测是在调用 Where 和代码中实际使用结果的位置(即实际调用该枚举器的 MoveNext 和 (get_)Current 的位置,例如来自 ToList)。

是的,findall 的惰性版本在哪里。 FindAll() 是 List 类型上的函数,它不是像 Where 那样的 LINQ 扩展方法。 List 上的 FindAll 方法,它是 returns 具有相同元素类型的新 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