What Type should myCustomDictionary.Values return?
Asked Answered
B

2

7

If you have the object Dictionary<k, v> myDictionary, then myDictionary.Values will be of type Dictionary<k, v>.ValueCollection and myDictionary.Keys will be of type Dictionary<k, v>.KeyCollection.

I don't understand why the type of myDictionary.Values is not something like IEnumerable<v>, IList<v> or something else.

Now, with that in mind, if I create a custom kind of dictionary; Dictionary2<k1, k2, v>, should myCustomDictionary.Values return an IEnumerable<v>, or a custom implement of ValueCollection? More importantly, why?

Barium answered 23/4, 2013 at 14:19 Comment(0)
P
5

Note that Dictionary<TKey, TValue>.ValueCollection does in fact implement ICollection<TValue> and therefore also IEnumerable<TValue>.

The reason why the property is typed the way it is is likely for performance reasons: since the methods of this class are not virtual, they can be exactly resolved during JIT compilation, instead of requiring vtable lookups for each method call at runtime. This effectively removes one level of indirection from each method you call on the collection. (It also gives the JIT the option to inline those method calls!)

Of course, you can implicitly convert the object to ICollection<TValue> if necessary, so there is no loss of functionality here, just a bit of (micro) optimization.

In your case, there is no reason you cannot return ICollection<TValue>, but you can return a more specific type if you would like. If you do, then you will have to explicitly implement the interface property IDictionary<TKey, TValue>.Values to satisfy the interface:

private ValueCollection valueCollection;

public ValueCollection Values
{
    get { return valueCollection; }
}

ICollection<TValue> IDictionary<TKey, TValue>.Values
{
    get { return valueCollection; }
}

This correctly implies that any performance benefit will only be given to consumers of the class if they are using a reference typed as your collection type; there will be no performance advantage if they take a reference to IDictionary<TKey, TValue>, as they will have to choice but to access your value collection through ICollection<TValue> anyway.

In my work, I have not found the performance difference to be significant enough to warrant returning anything more specific than ICollection<TValue>. Remember: always benchmark, and never prematurely optimize.

Pismire answered 23/4, 2013 at 14:23 Comment(2)
What, this answer has a lot of information in it. Thanks a lot sir!Barium
List<T> and Dictionary<TKey, TValue> are the most frequently used implementations of IList<T> and IDictionary<TKey, TValue>. As such, preventing unnecessary interface dispatch calls has an aggregate effect across the entire .NET ecosystem, and contributes to a mobile device power advantage that Java will never be able to touch (due to their overuse of overridable methods in infrastructure classes).Lankford
T
1

Dictionary<k, v>.ValueCollection implements IEnumerable<v> and Dictionary<k, v>.KeyCollection implements IEnumerable<k>. It's not like the results that are returned aren't enumerable.

By returning an actual class that implements IEnumerable rather than typing the result as IEnumerable they have the ability to include a bit of additional functionality as well. For example, both collections have a Count property, which isn't easily accessible from any IEnumerable.

Tartary answered 23/4, 2013 at 14:23 Comment(1)
Note that ICollection<T> has a Count property, and IDictionary<TKey, TValue>.Values returns an ICollection<T>. So any implementation of IDictionary<TKey, TValue> must return a Values object that supports the Count property anyway. The more-specific type of Dictionary<TKey, TValue>.Values does not in any way provide extra functionality that I can see.Pismire

© 2022 - 2024 — McMap. All rights reserved.