当我在.NET中有SortedDictionary<TK, TV>
并且我希望将其枚举为ICollection<KeyValuePair<TK, TV>>
它是否按预期顺序进行枚举?
具有最低密钥的KeyValuePair<TK, TV>
作为第一个返回,后面跟KeyValuePair<TK, TV>
第二个最低密钥等。
注意:只接受通过引用备份的答案。
答案 0 :(得分:10)
来自GetEnumerator的Reference:
“字典使用内部树以排序顺序维护。每个新元素都位于正确的排序位置,并且每次删除元素时都会调整树以维护排序顺序。枚举时,排序顺序维持。“
具体来说:“在枚举时,维护排序顺序。”
答案 1 :(得分:3)
是的,尽管你会发现很难找到明确说明 的文档。
虽然这种类型的四个GetEnumerator
重载中的每一个的文档都有关于返回“一个遍历集合的枚举器”的模糊陈述,但很明显它们应该生成等效的(按键排序)序列;请记住,排序字典意味着“表示按键排序的键/值对的集合”。例如,如果集合在foreach
循环和LINQ to Objects查询之间表现完全不同(即具有不同的枚举顺序),则高度非直观且令用户感到困惑。
我能做的最好的事情是为您提供您似乎感兴趣的两种GetEnumerator
方法的实现(从.NET 4.0开始)。它们是相同的 - 它们返回嵌套Enumerator
类型的实例,其构造函数的相同的参数。唯一的区别是第二次重载中的struct-type的装箱:
// Used when you do foreach(var kvp in dict) { ... }
public Enumerator<TKey, TValue> GetEnumerator()
{
return new Enumerator<TKey, TValue>
((SortedDictionary<TKey, TValue>) this, 1);
}
// Used when you do:
// foreach(var kvp in (ICollection<KeyValuePair<TKey, TValue>>)dict) { ... }
// or use LINQ to Objects on the collection.
IEnumerator<KeyValuePair<TKey, TValue>>
IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
return new Enumerator<TKey, TValue>
((SortedDictionary<TKey, TValue>) this, 1);
}
事实上,{em>略有不同实现的唯一GetEnumerator
重载是IDictionary.GetEnumerator
方法。这会更改构造函数调用的参数,以便生成的枚举器生成DictionaryEntry
个实例而不是KeyValuePair<,>
个实例。当然,枚举顺序仍然与其他重载相同。
答案 2 :(得分:1)
这取决于密钥的默认IComparer
实现,假设您没有传入密钥:
SortedDictionary(Of TKey,TValue)需要比较器实现来执行密钥比较。您可以使用接受comparer参数的构造函数指定IComparer(Of T)泛型接口的实现;如果未指定实现,则使用默认的通用比较器Comparer(Of T).Default。如果类型TKey实现System.IComparable(Of T)泛型接口,则默认比较器使用该实现。
查看SortedDictionary<TKey, TValue>
页面的Remarks
部分。
因此,如果您的密钥是string
,则会使用IComparable
的字符串实现,如果将使用int32
int32
实现。