作者:手机用户2602923801 | 来源:互联网 | 2023-02-01 11:44
我的任务是维护一些遗留代码.至少在我看来,我的前任对C#非常有经验.但是,我注意到他留下了一些奇怪的代码.以此为例:
Storage.Clients.RemoveAll(x => x == null || x.IsOutdated());
foreach(Client client in Storage.Clients) {
//do something
}
列表已被清除null和过时的客户端,但在我看来,如果这样做会更有效:
for(int i = 0; i
我的理由是,不是迭代两次(一次在RemoveAll中,然后在foreach中),它只迭代一次,可能会使性能翻倍.我在这里错过了什么吗?正如我所说,我的前任经验丰富的事实让我不确定.
1> Servy..:
什么更快,在一英里长的赛道上跑一圈,或在半英里长的赛道上跑两圈?你认为在半英里的赛道上跑两圈需要两倍的时间吗?
有两个循环,每个循环完成一个循环完成所有工作的一半,不会导致两倍的工作量.您将有实际的迭代逻辑的多一点的开销,但这是非常在几乎所有环境中微不足道.通常(这似乎是这里的情况)在循环体中完成的实际工作将大大压倒实际循环本身所需的工作量(增加循环变量,检查循环是否完成等) .
实际上,在您的示例中,原始代码要快得多.当你打电话时,RemoveAt
它需要重新订购被删除项目后最后一个项目,所以如果你打电话给它N次,那就是执行(平均)一半项目的N次重新排序; 你最后一点一点地向下移动同一个项目.当你调用RemoveAll
它时可以同时删除所有项目,并且它们会根据需要将所有项目向下移动一次,从而大大减少列表中项目的重新排序次数,从而转换为O(n ^ 2)操作进入O(n)操作.
正如Aomine的回答中所提到的,你的实现中还有一个错误,当你删除一个项目时,它不会调整循环索引,因此在进行任何其他考虑之前你需要修复它.
两者之间也存在语义差异,这可能是也可能不相关.如果"执行某些操作"查看列表并且是否已从其中删除过期项目,则程序可能会有不同的行为.(这里可能不相关,但一般来说,在考虑组合循环时,您需要考虑在执行任何第二类操作之前,是否将所有第一类操作应用于每个项目实际上很重要.)