Immutable value types should override Object.Equals to get better performance than the default implementation, which uses reflection, and should override Object.GetHashCode to avoid a bug in the default implementation. Immutable reference types should override Equals if they need to provide value equality semantics. (For example, String is a reference type, but provides value equality: two strings are equal if they have the same content, not just if they are the same object in memory.)
There are a lot of rules to follow to implement equality correctly. A concise list is presented in Framework Design Guidelines, 2nd Edition, sections 8.9.1 and 8.9.2. A detailed explanation of the rules can also be found in the documentation for Object.Equals, Implementing the Equals Method, and Guidelines for Implementing Equals and the Equality Operator(==).
Because it’s sometimes easier to see (and copy!) a reference implementation than to just read a list of rules, we’ve made sample EquatableClass and EquatableStruct implementations available.
Both types:
IEquatable<T>.Equals
and place the primary equality comparison in this method.Object.Equals
and implement the equality & inequality operators; these should all delegate to IEquatable<T>.Equals
.Object.GetHashCode
and provide an implementation that is consistent with Equals
.EquatableClass:
== null
will needlessly use the overloaded operator.EquatableStruct:
Our reference implementations also use helper methods from HashCodeUtility and ObjectImpl in order to simplify the implementation of GetHashCode and the overloaded operators.
Posted by Bradley Grainger on February 08, 2010