C# 依赖于未修改哈希集的迭代顺序 HashSet myHashSet=newhashset(); //迭代1 foreach(myHashSet中的对象myObject){…} //一些不修改myHashSet的指令 ... //迭代2 foreach(myHashSet中的对象myObject){…}

C# 依赖于未修改哈希集的迭代顺序 HashSet myHashSet=newhashset(); //迭代1 foreach(myHashSet中的对象myObject){…} //一些不修改myHashSet的指令 ... //迭代2 foreach(myHashSet中的对象myObject){…},c#,mono,ienumerable,hashset,C#,Mono,Ienumerable,Hashset,在两次迭代中,myHashSet的对象是否会以相同的顺序枚举?确实有两种可能的答案 第一个是“是的,因为枚举一个HashSet是确定的,如果你不相信我的话,你可以简单地查看源代码” 第二个是“否,因为如果您想了解技术,HashSet.GetEnumerator()的文档没有说明顺序是确定的,因此明天实现可能会改变” 用第一个答案来完成工作,你不会错的。如果您想绝对肯定,当然可以使用myHashSet.ToArray()并仅对其进行迭代,但仅仅为了技术上的原因而引入一个副本可能会有些过火。在这种情

在两次迭代中,
myHashSet
的对象是否会以相同的顺序枚举?

确实有两种可能的答案

第一个是“是的,因为枚举一个
HashSet
是确定的,如果你不相信我的话,你可以简单地查看源代码”

第二个是“否,因为如果您想了解技术,HashSet.GetEnumerator()的文档没有说明顺序是确定的,因此明天实现可能会改变”

用第一个答案来完成工作,你不会错的。如果您想绝对肯定,当然可以使用
myHashSet.ToArray()
并仅对其进行迭代,但仅仅为了技术上的原因而引入一个副本可能会有些过火。在这种情况下,实现必须不遗余力地实现一个不确定的枚举


不过,有一个重要的警告:您应该强调的是,
HashSet
不会在两次枚举之间被修改,因为实现在集合发生更改时更改顺序是合理的(这取决于项目在内部的存储方式)。

根据
HashSet
()的参考源,在没有集合修改的情况下,迭代顺序是可预测的

HashSet<object> myHashSet = new HashSet<object>();

// Iteration 1
foreach (object myObject in myHashSet) { ... }

// Some instructions THAT DO NOT MODIFY myHashSet
...

// Iteration 2
foreach (object myObject in myHashSet) { ... }

虽然并没有技术上的原因说明顺序会改变,因为它需要特殊的代码,根据f源代码集合之外的内容改变顺序。。。但是依赖它不是一个好主意,因为唯一的官方文档是:“如果订单或元素复制比应用程序的性能更重要,请考虑使用<代码>列表<代码>类,连同<代码>排序< /代码>方法。”您还可以检查参考源以查看它是如何实现的。(同样,依赖实现细节通常不是个好主意)。也许你可以使用SortedSet对象而不是HashSet。@AlexeiLevenkov:因为问题被标记为“mono”,Microsoft参考源可能与此无关。虽然,很明显,Mono团队会疯狂地偏离,并且任何合理的独立实现仍然是确定性的。谢谢你的回答。dasblinkenlight的回答大致相同,但我很欣赏这些片段。我是在处理Mono。但是如果你看一下它似乎还以可预测的顺序遍历集合。
public bool MoveNext() {
    if (version != set.m_version) {
        throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_EnumFailedVersion));
    }

    while (index < set.m_lastIndex) {
        if (set.m_slots[index].hashCode >= 0) {
            current = set.m_slots[index].value;
            index++;
            return true;
        }
        index++;
    }
    index = set.m_lastIndex + 1;
    current = default(T);
    return false;
}
var myList = myHashSet.ToList();
foreach( var obj myObject in myList) ...
// Some instructions (may or may not modify myHashSet, it no longer matters)
foreach( var obj myObject in myList) ...