# Compiler Warning CS0659
Jan 30, 2016 9 minute readThe majority of C# developers have found Compiler Warning CS0659 at some point of their careers. Ignoring this warning can produce unexpected program behavior. The following is summary of the impact this warning can have on a codebase and how to prevent it.
TL;DR: Override GetHashCode
whenever Equals
is overridden
Reference Equality
Let’s consider the following Dog
class in C#.
And the following usage of it.
The snippet of code from above prints False
. For reference types the default implementation of Equals
compares the references instead of the values where they are pointing to. 1
Github Commit 5d488e6d6127111167e9a8f36fe83a771e36cb9c contains the sample source code up to this point
Semantic Equality
Let’s enhance the Dog
class so that comparisons between Dogs
have a better semantic meaning.
After overriding the Equals
method the following code prints True
.
Github Commit 7abeb0d9b8dbf7c09124485fb0f7e3bd18257b18 contains the sample source code up to this point
Warning CS0659
Once we compile the code we get the following warning.
warning CS0659: ‘Dog’ overrides Object.Equals(object o) but does not override Object.GetHashCode()
Compiler Warning (level 3) CS0659 is straightforward and direct to the point: If you override Equals
you need to override GetHashCode
.
The Problem
This is not one of those warnings that can safely be ignored. 2 It will come back to bite you. Let’s consider the following usages of the Dog
class.
The code from above prints False
because fido
cannot be found in dogShelter
.
Why?
Overriding Equals
is not enough. The GetHashCode
method provides a numeric value for quick equality checks such as those used in collections like Dictionary
and HashTable
. 3
Github Commit d91504bfedcb60ab86fffe72dcac88fb775405de contains the sample source code up to this point
Solution
Override GetHashCode
whenever Equals
is overridden. The following is an implementation of Dog
where GetHashCode
is overridden. 4
With this implementation of Dog
in place, fido
can be found in the dogShelter
.
Github Commit 98c9adc1fff2aee2362fd494f3a43cdb7f4d3d8a contains the sample source code up to this point
In a nutshell
Object.GetHashCode
is as important as Object.Equals
for equality matters. Never override one without the other.
Update: Equality is Hard 5
Since Dog
is a mutable object GetHashCode
will return different values when either of its properties change making it impossible to be found in dictionaries. Down the rabbit hole we go. To overcome this issue we have to make its properties readonly.
Now our Program looks as follows:
Github Commit dffbd97927070b05c623192a788a33b97e7101c7 contains the sample source code up to this point
Value Types to the Rescue
An easier way to get rid of all of this Equality nonsense would be to make Dog
a value type. That way we’d get equality for free.
Github Commit b756e87a63abec9ea8c069bc5d9c09b2a2376311 contains the sample source code up to this point
-
Warning levels, what are they, which level to use, and should they be treated as errors? ↩
-
ReSharper users can benefit from automatic generation of
GetHashCode
implementations ↩