Overriding GetHashCode for mutable objects?
Solution 1:
How does that work if the fields that it's based on are mutable?
It doesn't in the sense that the hash code will change as the object changes. That is a problem for all of the reasons listed in the articles you read. Unfortunately this is the type of problem that typically only show up in corner cases. So developers tend to get away with the bad behavior.
Also what if I do want dictionary lookups etc to be based on reference equality not my overridden Equals?
As long as you implement an interface like IEquatable<T>
this shouldn't be a problem. Most dictionary implementations will choose an equality comparer in a way that will use IEquatable<T>
over Object.ReferenceEquals. Even without IEquatable<T>
, most will default to calling Object.Equals() which will then go into your implementation.
Basically in most of the executing code I want reference equality and I always use == and I'm not overriding that.
If you expect your objects to behave with value equality you should override == and != to enforce value equality for all comparisons. Users can still use Object.ReferenceEquals if they actually want reference equality.
I used to assume that the framework always uses == and not Equals to compare things
What the BCL uses has changed a bit over time. Now most cases which use equality will take an IEqualityComparer<T>
instance and use it for equality. In the cases where one is not specified they will use EqualityComparer<T>.Default
to find one. At worst case this will default to calling Object.Equals
Solution 2:
If you have a mutable object, there isn't much point in overriding the GetHashCode method, as you can't really use it. It's used for example by the Dictionary
and HashSet
collections to place each item in a bucket. If you change the object while it's used as a key in the collection, the hash code no longer matches the bucket that the object is in, so the collection doesn't work properly and you may never find the object again.
If you want the lookup not to use the GetHashCode
or Equals
method of the class, you can always provide your own IEqualityComparer
implementation to use instead when you create the Dictionary
.
The Equals
method is intended for value equality, so it's not wrong to implement it that way.