gpt4 book ai didi

c# - LINQ删除,然后foreach迭代或为迭代并在循环中删除?

转载 作者:太空宇宙 更新时间:2023-11-03 17:38:32 25 4
gpt4 key购买 nike

我的任务是维护一些旧代码。至少在我看来,我的前任对C#很有经验。但是,我注意到他留下了一些奇怪的代码。以这个为例:

Storage.Clients.RemoveAll(x => x == null || x.IsOutdated());
foreach(Client client in Storage.Clients) {
//do something
}


该列表将清除null和过时的客户端,但是在我看来,如果这样做,它将更加高效:

for(int i = 0; i < Storage.Clients.Count; i++) {
if(Storage.Clients[i] == null || Storage.Clients[i].IsOutdated())
Storage.Clients.RemoveAt(i);
else
//do something
}


我在这里的理由是,它不会重复两次(一次在RemoveAll中,然后在foreach中),而是仅重复一次,从而可能使性能加倍。我在这里想念什么吗?正如我所说,我的前任有经验的事实使我不确定。

最佳答案

在一个英里长的赛道上跑一圈,或者在一个半英里长的赛道上跑两圈,哪个更快?您是否认为在半英里的赛道上进行两圈会花费两倍的时间?

有两个循环,每个循环完成一个循环的工作量只有一个循环的一半,却不会导致两倍的工作量。您将需要更多实际迭代逻辑的开销,但这在几乎所有情况下都是微不足道的。通常(在这里似乎是这种情况),在循环主体中完成的实际工作将大大淹没实际循环本身所需的工作量(增加循环变量,检查循环是否完成等)。 。

实际上,在您的示例中,原始代码要快得多。调用RemoveAt时,它需要对已删除项目之后的最后一个项目中的每个项目重新排序,因此,如果您调用N次,则将执行(平均)一半项目的N次重新排序。您最终会一遍又一遍地将同一项目向下移动一点。当您调用RemoveAll时,它可以一次删除所有项目,并且它们可以一次将所有项目向下移动所有数量,从而大大减少了列表中该项目的重新订购次数,将其变为O (n ^ 2)运算变成O(n)运算。

如Aomine的回答中所述,您的实现中还存在一个错误,该错误在删除项目时不会调整循环索引,因此,您甚至需要进行任何其他考虑之前,都必须先对其进行修复。

两者之间在语义上也有所不同,这可能相关也可能不相关。如果“执行某些操作”在列表中,则程序的行为可能会有所不同,并且会受到是否已从其中删除过时的项目的影响。 (这里可能无关紧要,但是通常,在考虑组合循环时,您需要考虑在执行第二种类型的任何操作之前,将所有第一种类型的操作应用于每个项目是否真的很重要。)

关于c# - LINQ删除,然后foreach迭代或为迭代并在循环中删除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44551825/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com