FindAll Vs Where

本文关键字:Where Vs FindAll | 更新日期: 2023-09-27 18:17:18

我有一个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));

FindAll Vs Where

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

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

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

是的,Where是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;              

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

了解LINQ和延迟执行