我想要基于LINQ谓词过滤IEnumerable<T>
。我像往常一样尝试在Where
上使用IEnumerable
,但这次我偶然发现了一些有趣的事情。当使用谓词调用IEnumerable
上的Where时,我得到一个空列表作为回报。我知道它必须生成一个包含两个项目的列表。如果我改为使用FindAll
,使用相同的谓词,则会产生正确的结果。
任何人都可以向我解释,为什么会这样?我一直认为Where
是FindAll
的懒惰版本,它还返回了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));
答案 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循环中执行