I ran into this today when unit testing a generic dictionary.
System.Collections.Generic.Dictionary<int, string> actual, expected; actual = new System.Collections.Generic.Dictionary<int, string> { { 1, 'foo' }, { 2, 'bar' } }; expected = new System.Collections.Generic.Dictionary<int, string> { { 1, 'foo' }, { 2, 'bar' } }; Assert.AreEqual(expected, actual); //returns false
fails except when actual == expected (object references are the same). Obviously, actual.Equals(expected) returns false as well.
Fine, but if the implementation of System.Collections.Generic.Dictionary<int, string>.Equals only does reference equality, what’s the point of IEquatable? In other words, why is there no baked-in way to do value equality for generic collections?
Edit Thanks for the responses so far. Obviously my example is using value types, but I think my complaint holds for all objects. Why can’t a generic collection equality just be a union of equalities of its types? Unexpected behavior doesn’t really cut it since there are separate provisions for finding reference equality. I suppose this would introduce the constraint of collections only holding object that implement IEquatable, as Konrad Rudolph points out. However, in an object like Dictionary, this doesn’t seem too much to ask.
Probably because it’s hard to formulate in generic terms, since this would only be possible if the value type (and key type) of the dictionary also implemented
IEquatable. However, requiring this would be too strong, makingDictionaryunusable with a lot of types that don’t implement this interface.This is an inherent problem with constrained generics. Haskell provides a solution for this problem but this requires a much more powerful and complicated generics mechanism.
Notice that something similar is true for
IComparablein comparison with containers, yet there is support for this, usingComparer<T>.Defaultif necessary.