开发者

When SortedDictionary is enumerated does it return KeyValuePairs in expected order?

开发者 https://www.devze.com 2023-02-28 01:57 出处:网络
When I have SortedDictionary<TK, TV> in .NET and 开发者_运维百科I want to enumerate it as ICollection<KeyValuePair<TK, TV>> does it enumerate in expected order?

When I have SortedDictionary<TK, TV> in .NET and 开发者_运维百科I want to enumerate it as ICollection<KeyValuePair<TK, TV>> does it enumerate in expected order?

That is KeyValuePair<TK, TV> with lowest key is returned as first, folloved by KeyValuePair<TK, TV> with second lowest key etc.?

Note: Only answer backed up by reference will be accepted.


From the Reference for GetEnumerator:

"The dictionary is maintained in a sorted order using an internal tree. Every new element is positioned at the correct sort position, and the tree is adjusted to maintain the sort order whenever an element is removed. While enumerating, the sort order is maintained."

Specifically: "While enumerating, the sort order is maintained."


Yes definitely, although you are going to find it very hard to find documentation that clarifies this precisely.

Although the documentation for each of the four GetEnumerator overloads on this type make vague statements about returning "an enumerator that iterates through a collection", it is obvious enough that they should produce equivalent (sorted by key) sequences; remember that a sorted-dictionary is meant to "represent a collection of key/value pairs that are sorted on the key." It would be highly unintuitive and confusing for users if a collection behaved completely differently (i.e. with a different enumeration order) between a foreach loop and a LINQ to Objects query, for example.

The best I can do is provide you with the implementations of the two GetEnumerator methods you appear to be interested in (as of .NET 4.0). They are identical - they return an instance of the nested Enumerator type, with the same arguments for its constructor. The only difference is the boxing of the struct-type in the second overload:

// 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);
}

In fact, the only GetEnumerator overload that has a slightly different implementation is the IDictionary.GetEnumerator method. This changes an argument to the constructor-call such that the resulting enumerator produces DictionaryEntry instances rather than KeyValuePair<,> instances. Of course, the enumeration order will still be the same as with the other overloads.


It depends on the default IComparer implementation of the key, assuming you are not passing one in:

SortedDictionary(Of TKey, TValue) requires a comparer implementation to perform key comparisons. You can specify an implementation of the IComparer(Of T) generic interface by using a constructor that accepts a comparer parameter; if you do not specify an implementation, the default generic comparer Comparer(Of T).Default is used. If type TKey implements the System.IComparable(Of T) generic interface, the default comparer uses that implementation.

Look at the Remarks section of the SortedDictionary<TKey, TValue> page.

So, if your key is a string, the string implementation of IComparable will be used, if an int32 the int32 implementation will be used.

0

精彩评论

暂无评论...
验证码 换一张
取 消