".where(...).Any()"和"..Any(...)"之间的性能差异。"

5
给定一个内存中的对象列表,我运行了以下两个表达式:

可能重复:
LINQ扩展方法 - Any() vs. Where() vs. Exists()

myList.where(x => x.Name == "bla").Any() 

对比

myList.Any(x => x.Name == "bla")

后者始终是最快的,我认为这是由于Where枚举所有项所致。但是,在没有匹配项时也会发生这种情况。
我不确定确切的原因。是否存在任何情况,其中查询Nhib时不会出现性能差异?
干杯。

1
不应该有任何区别。https://dev59.com/42kw5IYBdhLWcg3wJHGF - Tim Schmelter
SearchQueryDTO是一个类,其中有一个名为Name的字符串属性。IList<SearchQueryDTO> myList = new List<SearchQueryDTO>(); for (int i = 0; i < 500; i++) { myList.Add(new SearchQueryDTO { Name = i.ToString()}); } var timer2 = Stopwatch.StartNew(); var res2 = myList.Any(x => x.Name == "499"); var time2 = timer2.Elapsed; //大约0.5毫秒 var timer = Stopwatch.StartNew(); var res = myList.Where(x => x.Name == "499").Any(); var time1 = timer.Elapsed; //大约3.5毫秒 - clonesegg
@JonSkeet 他一定是指 ==,因为使用 = 会导致编译错误 "无法将类型 'string' 转换为 'bool'"。 - Doctor Jones
@marky:我会编辑你的帖子,除非它是非常小的代码片段,否则不要在评论中放置代码... - James Michael Hare
这个问题不是重复的,投票重新打开。 - ataravati
显示剩余7条评论
3个回答

11

Any()方法与谓词可以在没有迭代器(yield return)的情况下执行任务。而使用Where()会创建一个迭代器,这会对性能产生一定的影响(尽管很小)。

因此,就性能而言(略微),最好使用带有谓词(x => x.Name == "bla")的Any()形式。我个人认为这种方式更易读...

顺便说一句,Where()并不一定枚举所有元素,它只是创建了一个迭代器,将在请求时遍历元素,因此在Where()后调用Any()将驱动迭代,在找到满足条件的第一项后停止遍历。

因此,性能差异不是Where()遍历所有项目(在Linq-to-objects中),因为它实际上不需要(除非它找不到满足条件的项),而是Where()子句必须设置一个迭代器来遍历元素,而带有谓词的Any()则不需要。


詹姆斯,感谢您为我解决这个问题!我运行了几次,总是得到这个性能差异。 - clonesegg

2
假设您将where更正为Where并将=更改为==,我期望“带有谓词的任意”版本执行速度会稍微快一些。但是,我期望差异显著的情况很少,因此您应该首先考虑可读性。
恰好,从可读性的角度来看,我通常更喜欢“带有谓词的任意”版本,所以您在两个方面都胜利了-但是您应该首先选择您认为更易读的方式。在您实际关心的场景中测量性能,如果某个代码部分未按您需要的方式执行,则考虑微调它-当然,在每个步骤中进行测量。

使用谓词的任何+1,注重可读性。 - Doctor Jones

0
我相信这是由于 `Where` 枚举所有项目导致的。
如果 `myList` 是一个内存中的集合,那么不会。`Where` 方法使用延迟执行,因此它只会枚举需要确定结果的项目数量。在这种情况下,您不会看到 `.Any(...)` 和 `.Where(...).Any()` 之间有任何显着差异。
有没有什么情况下这种性能差异不会发生,例如如果查询 Nhib?
是的,如果 `myList` 是一个数据源,将采用方法生成的表达式并翻译为要在其他地方运行的查询(例如LINQ To SQL),则可能会看到差异。翻译表达式的代码只是更好地翻译其中一种表达式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接