【问题标题】:Is the order of objects returned by FOREACH stable?FOREACH 返回的对象顺序是否稳定?
【发布时间】:2010-09-15 02:09:57
【问题描述】:

假设对同一个集合的两次迭代将以相同的顺序返回对象是否安全?显然,假设集合没有被改变。

【问题讨论】:

    标签: c# .net collections foreach ienumerable


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      简短的回答 - 是的。

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

      但是每次使用 foreach 循环遍历一个未修改的集合时,您都会得到相同的结果。

      【讨论】:

      • hmmmm... 看来我们俩都做了同样的事情。写了一句话,贴出来,然后马上编辑详细说明。
      • 确实如此。我认为您的答案比我的更合适,希望 OP 将其标记为权威。当然似乎赢得了普选:)
      • 将其标记为最终答案的问题当然在于它不准确!
      • @Steve Morgan,他确实通过说对于大多数集合,“是”来限定它,这取决于集合类型。我认为你的观点很好,但要说它不准确......我不确定。
      • 我认为这是不正确的。 目前一个字典可以被枚举多次并且会以相同的顺序返回项目,但是文档提到值的顺序是undefined,这意味着它可以改变——例如在下一个 .NET 版本中——如果你依赖未记录的行为,你的代码就会中断。详细说明:List 承诺以特定顺序返回项目,您可以依赖该行为。例如,Dictionary 没有做出任何此类承诺,因此行为可能随时改变。
      【解决方案3】:

      除非您知道您正在迭代的类的具体实现,否则您无法保证这一点。

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

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

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

      【讨论】:

        【解决方案4】:

        虽然对于所有内置集合以及可能存在的任何健全的集合类,答案都是“是”,但文档没有为IEnumerable 制定任何约束条件。因此,没有什么告诉我们每次迭代都必须是稳定的。

        我可以想象以下用例:

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

        这很可能被实现为一个为每次迭代产生不同排序的类。

        所以——如果您还想考虑奇怪的边缘情况,答案应该是“”。

        【讨论】:

        • 呃,詹姆斯改变了答案吗?当我写我的时候,它仍然是原创的。 :-/
        • 顺序不一致的绝佳例子!
        【解决方案5】:

        虽然通常会以相同的顺序返回元素,但绝对不能保证。它完全依赖于集合类的内部实现。

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

        简而言之,除非你知道集合类的内部实现,否则不要假设任何关于顺序的事情。

        【讨论】:

          【解决方案6】:

          Linq 为此定义了IOrderedEnumerable 接口。

          【讨论】:

            【解决方案7】:

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

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

            【讨论】:

              【解决方案8】:

              我会说,对于大多数收藏来说,假设这一点是安全的。某个集合可能会以非确定性方式实现枚举器,但这并不超出可能性范围,但这可能不会发生......

              【讨论】:

              • 取决于您是否喜欢“可能”工作的代码。就我个人而言,我喜欢比这更有信心!
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-09-17
              • 2011-02-24
              • 2010-10-14
              • 2010-10-06
              相关资源
              最近更新 更多