Num*_*mid 4 c# mono ienumerable 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) { ... }
Run Code Online (Sandbox Code Playgroud)
myHashSet在两次迭代中,是否将对象的对象枚举顺序相同?
确实有两个可能的答案。
第一个是“是的,因为枚举a HashSet是确定性的,如果您不相信我,您可以直接查看源代码”。
第二个是“不,因为如果您想获取技术,文档HashSet<T>.GetEnumerator()中不会说顺序是确定性的,那么明天的实现可能会改变”。
选择第一个答案来完成工作不会错。如果您想绝对肯定地使用,当然可以myHashSet.ToArray()仅在此基础上使用和迭代,但是仅出于技术性考虑而引入副本可能会显得过大。在这种情况下,实现将不得不去的出路来实现的枚举不确定性。
不过,有一个重要的警告:强调HashSet在枚举之间不进行修改是您的正确做法,因为实现在集合更改时更改顺序是合理的(这将取决于项目在内部的存储方式)。
根据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;
}
Run Code Online (Sandbox Code Playgroud)
但是不太可能,这可能会在.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) ...
Run Code Online (Sandbox Code Playgroud)