我有一个项目列表,我想迭代它们的一个子集。现在,我想知道从列表中删除不需要的项目然后循环它之间是否存在性能影响差异;或者只是过滤for循环中的列表。
这是一个例子。
RemoveAll方法:
list.RemoveAll(o => !someOtherList.Contains(o.Property));
foreach (var i in list)
{
}
Where方法:
foreach (var i in list.Where(o => someOtherList.Contains(o.Property))
{
}
据我所知,第一种方法实际上是操纵列表中的内容,而第二种方法则不会。这并不关心我。我更关心的是第二种方法中的过滤器是否适用于每次迭代,或者C#是否足够智能来创建子集并且只循环遍历该子集(几乎就像第一种方法带有临时变量)。
答案 0 :(得分:5)
我更关心的是第二种方法中的过滤器是否是 应用于每次迭代或C#是否足够聪明以创建 子集,只循环通过该子集(几乎与第一个一样 使用临时变量的方法)
Linq的Where
使用yield,以便在请求时一次返回一个元素。
所以实际上在第二种方法中所做的是:
1-遍历列表
2-检查Current元素是否与条件匹配(通过someOtherList循环,除非它是一个特殊的查找数据结构,例如。HashSet
)
3-一旦我们发现第一个元素返回它
4-执行foreach body逻辑
5-继续搜索我们在第3步停止的地方
如果您决定根据foreach块内的某些条件决定中断,那么可能不会在该点扫描所有列表,这在某些情况下可能会在大型列表上提升性能。
答案 1 :(得分:1)
作为对其他人已经说过的内容的补充,如果循环操作与您所显示的一样,原始性能将不会产生可忽略的差异。
但是,第一个需要具有物化列表,而后者需要使用IEnumerable。此外,对于要运行的循环内容,首先需要首先实现,然后才开始循环内容。对于某些列表和另一个列表,使用NOP循环的IOW可能需要大约10秒才能完成。当循环中有一些工作(可能),然后第一个在进入循环之前花费10秒,然后你需要时间进行循环处理。后者的OTOH会直接命中它找到的每个元素的循环。如果循环内容是一个耗时的操作,而且可以asynch完成,那么后者将是一个明显的赢家。