FOREACH返回的对象顺序是否稳定?

时间:2020-03-06 15:04:39  来源:igfitidea点击:

是否可以安全地假设同一集合上的两个事件将以相同的顺序返回对象?显然,假定该集合没有进行其他更改。

解决方案

简短的回答是。

但是,显然,取决于集合的类型(例如字典),集合中项目的顺序可能与插入时的顺序不完全相同。

但是,每次使用foreach循环遍历单个未修改的集合时,我们将获得相同的结果。

这取决于收集类型。对于大多数收藏,答案是"是"。

但是,这不能保证。集合类型的文档应指定是否这样做,但与大多数情况一样,通常会忽略该详细信息。但是,如果不稳定,那么如果文档中没有提及,将是一个巨大的疏忽。

我要说的是,对于大多数收藏而言,可以安全地假设这一点。某个集合可以以不确定的方式实现枚举器并非没有可能,但这可能不会发生……

对于所有内置集合以及可能存在的任何理智的集合类,答案都是肯定的,但是文档中没有为" IEnumerable"制定任何约束。因此,没有什么可以告诉我们每次迭代都必须稳定。

我可以想象以下用例:

foreach (int i in new Shuffler(1, 2, 3, 4, 5, 6, 7, 8, 9))
    Console.WriteLine(i);

这很可能被实现为一个类,该类对于每次迭代都会产生不同的顺序。

因此,如果我们还想考虑奇怪的临界情况,答案应该是"否"。

通常情况下,元素将以相同顺序返回,但绝对不能保证。它完全取决于collection类的内部实现。

例如,我可以看到一个专门用于以随机顺序返回元素的集合类的案例。

简而言之,除非我们知道collection类的内部实现,否则不要假设任何有关该顺序的信息。

我们不能保证这一点,除非我们知道要迭代的类的具体实现。

具有定义的元素顺序的集合(例如List <T>)将以稳定的顺序枚举。

对于对象状态不变的集合,元素很有可能会以相同的顺序返回,例如Dictionary <K,V>,尽管规范不保证。

作为一个可能不是这种情况的示例,我们可以想象一个基于哈希表的字典实现,该实现以异步方式压缩或者调整表的大小。这样的实现将不能保证稳定的迭代顺序。

关于"未修改"(NM的回复),请注意,许多复杂的容器(例如Dictionary)不能保证保留顺序。有时添加一个项目会使它最后出现(给人以保留顺序的印象),有时会导致内部存储桶重新组织,从而给出完全不同的顺序。

诸如SortedList <,>之类的东西显然具有自己的规则。