Implementing IEquatable is not enough to use a class as a Dictionary key

Note to future self: it is not enough to implement IEquatable<T> to use a class as a Dictionary key.

Today I needed a Dictionary with a composite key, a combination of several values. So I quickly cooked up a class with public properties to cover the values and for ease of use, a constructor to quickly set those values. But to be able to use it as a dictionary key, I would need a little more. Per default, classes are only checked for reference equality, which makes sense. But I would need to have the system evaluate two separate instances of this class as equal, if all of their properties were equal.

Great! I quickly added an implementation that compared all of the properties and fired up my application. All retrieval attempts from the dictionary failed, they did not return any results. I set a breakpoint on my Equals implementation only to find it was never hit.

As it turned out, I had been a little too quick. Implementing IEquatable is not enough! It is not obvious from the documentation (at least it wasn’t to me), but you also have to override GetHashCode(), because the dictionary relies on it to distinguish keys before it even looks at Equals(). After I added a GetHashCode() override, suddenly the Equals implementation was hit and the dictionary worked as I had intented.

As a bonus, adding GetHashCode() was easily done using my favorite ReSharper plugin: hit Alt+Ins, Equality members. Tick the properties that need to be included in the comparison, and all the necessary code is generated for you. But, of course, it is also not that hard to add it on your own, just don’t forget to do that.

Advertenties

Share this:

Vind ik leuk:

Gerelateerd

Over ShiftkeyI am Maarten, owner of and chief software developer for Shiftkey software development from The Netherlands. I will be writing mainly about things I run into when programming in C# or Delphi.