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) { ... }
在两次迭代中,myHashSet
的对象是否会以相同的顺序枚举?
答案 0 :(得分:4)
真的有两种可能的答案。
第一个是“是的,因为列举HashSet
是确定性的,如果你不相信我,你可以简单地查看来源。”
第二个是“不,因为如果你想获得技术,HashSet<T>.GetEnumerator()
的文档并没有说订单是确定性的,那么明天实施可能会改变”。
完成工作的第一个答案是不错的。如果你想绝对肯定,你当然可以使用myHashSet.ToArray()
并且只对它进行迭代,但是为了技术性而引入一个副本可能会有点过分。在这种情况下,实现必须远离以实现不确定性的枚举。
一个重要的警告:强调HashSet
未在枚举之间进行修改是没有错的,因为 对于实现更改顺序是合理的设置更改(这取决于项目在内部的存储方式)。
答案 1 :(得分:4)
根据HashSet
(link)的参考来源,迭代次序在没有设定修改的情况下是可预测的。
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;
}
但不太可能,这可能会在.NET平台的未来版本或其他实现中发生变化。要确保顺序保持不变,请在第一次迭代时从集合中创建一个列表,并使用该列表进行第二次迭代:
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) ...