FindAll与哪里

时间:2015-10-12 09:03:46

标签: c# .net linq list ienumerable

我想要基于LINQ谓词过滤IEnumerable<T>。我像往常一样尝试在Where上使用IEnumerable,但这次我偶然发现了一些有趣的事情。当使用谓词调用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));

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

您可以在此处找到答案:LINQ, Where() vs FindAll()。基本上如果你在&#34; Where&#34;上调用.ToList()。他们会是一样的。

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

答案 2 :(得分:1)

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

主要区别(除了它们实现的内容:IEnumerable vs. 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