Is there a "contract" for the interface IDictionary<TKey, TValue>
I should follow when implementing value replacement with this[key] = newValue
? An example:
IDictionary<MyKey, string> dict = CreateEmptyDict();
var k1 = new MyKey(123);
var k2 = new MyKey(123);
dict.Add(k1, "foo");
dict[k2] = "bar";
k1 and k2 are such that k1.Equals(k2)
and they have the same hash code, but they are reference types so ReferenceEquals(k1, k2) == false
.
The BCL Dictionary<TKey, TValue>
will contain (k1, "bar")
.
My question is: is this a "contract" I really should follow for any implementation of IDictionary<TKey, TValue>
or can I let my implementation contain (k2, "bar")
if it is easier to do so in the underlying data structure?
It's implementation-specific at least to some extent. For example, Dictionary<,>
allows you to specify an IEqualityComparer<T>
to use to check keys for equality, and SortedDictionary<,>
doesn't use Equals
and GetHashCode
at all - instead, it uses IComparer<T>
to check for key ordering.
It would be entirely reasonable to create a dictionary which relied on solely reference equality - but make sure you document that very carefully. I would note that you don't really need to implement IDictionary<,>
yourself to do that... you just need to use Dictionary<,>
and custom equality comparer which uses reference equality and RuntimeHelpers.GetHashCode()
to fetch the hash code that Object.GetHashCode()
would use if it weren't overridden.
It would be very, very weird for a dictionary to be implemented so that you could add the exact same value as a key multiple times - but how you judge whether keys are actually equal is a different matter, IMO.
See more on this question at Stackoverflow