枚举SortedDictionary时它是否按预期顺序返回KeyValuePairs?

时间:2011-04-23 15:58:00

标签: c# .net ienumerable idictionary sorteddictionary

当我在.NET中有SortedDictionary<TK, TV>并且我希望将其枚举为ICollection<KeyValuePair<TK, TV>>它是否按预期顺序进行枚举?

具有最低密钥的KeyValuePair<TK, TV>作为第一个返回,后面跟KeyValuePair<TK, TV>第二个最低密钥等。

注意:只接受通过引用备份的答案。

3 个答案:

答案 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实现。