C#foreach循环 - 订单*稳定*保证?

时间:2012-07-27 01:36:46

标签: c# collections foreach

假设我有一个给定的集合。在没有以任何方式更改集合的情况下,我使用foreach循环其内容两次。除了宇宙射线,什么不是,它绝对保证两个循环中的顺序是一致的吗?

或者,如果HashSet<string>包含许多元素,那么可能导致以下注释行的输出不相等:

{
    var mySet = new HashSet<string>();
    // Some code which populates the HashSet<string>

    // Output1
    printContents(mySet);

    // Output2
    printContents(mySet);
}

public void printContents(HashSet<string> set) {
    foreach(var element in set) {
         Console.WriteLine(element);
    }
}

如果我能得到一般性答案,解释导致实施不符合上述标准的原因,将会有所帮助。但具体来说,我对DictionaryList和数组感兴趣。

4 个答案:

答案 0 :(得分:12)

数组枚举保证顺序。

预计

ListList<T>将提供稳定的订单(因为预期它们会实现顺序索引的元素)。

字典,HashSet明确不保证顺序。 2个一个接一个地迭代项目的调用不太可能以不同的顺序返回项目,但是没有保证或期望。不应该指望任何特定的订单。

Dictionary / HashSet的排序版本按排序顺序返回项目。

其他IEnumerable对象可以随意执行任何操作。通常,实现迭代器的方式与用户的期望相匹配。即如果提供了明确的顺序,那么具有隐式顺序的东西的枚举应该是稳定的 - 预期是稳定的。对未指定顺序的数据库的查询应该以半随机顺序返回项目。

请检查此问题以获取链接:Does the foreach loop in C# guarantee an order of evaluation?

答案 1 :(得分:4)

实现IEnumerable<T>的所有内容都以自己的方式实现。没有一般保证任何给定的集合必须确保稳定性。

如果您具体提到Collection<T>http://msdn.microsoft.com/en-us/library/ms132397.aspx),我在其MSDN参考中没有看到任何特定保证,即排序是一致的。

它可能是一致的吗?是。有书面保证吗?不是我能找到的。

答案 2 :(得分:3)

对于许多C#集合,有已排序版本的集合。例如,HashSetSortedSet,而DictionarySortedDictionary。如果您正在处理订单不重要的事情,例如Dictionary,那么您不能假设循环次序每次都会以相同的方式运行。

答案 3 :(得分:0)

根据HashSet<T>的示例,我们现在要检查源代码:HashSet:Enumerator

实际上,迭代了Slot[] set.m_slots数组。 数组对象仅在方法TrimExcessInitialize(两者都只在构造函数中调用),OnDeserializationSetCapacity中更改(仅由{{{ 1}}和AddIfNotPresent)。

AddOrGetLocation的值只会在更改m_slotsHashSetClearRemoveAddIfNotPresent元素的方法中更改,IntersectWith)。

所以是的,如果没有触及该集合,它将以相同的顺序枚举。

Dictionary:Enumerator以完全相同的方式工作,迭代只在调用此类非读取方法时才会更改的SymmetricExceptWith