IDictionary<TKey, TValue> implementation and contract for replacing values

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?

Jon Skeet
people
quotationmark

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.

people

See more on this question at Stackoverflow