The ReferenceEquals() method.
This is used to test if two given variables point (the symbol references) to the same object. It is literally equivalent to ((object)a) == ((object)b)
. If you override the comparison operator (==
) then ReferenceEquals
maintains a way to access the default behaviour.
However, if you are dealing with a value type (e.g. a struct) then this will always return false. This is because the comparison boxes each value type to a new object so naturally the references will not be equal.
The virtual Equals() method. (System.Object)
This is the default way to semantically compare two objects (of any type). Each class overrides this as they choose. By default it is equivalent to a CLR call (InternalEquals) that basically compares memory references.
Note, if two objects return true for Equals()
then GetHashCode()
on each of them must be equal. However, if the hash codes for two objects are value equivalent (i.e. obj1.GetHashCode() == obj2.GetHashCode()
) this does not means that Equals()
is true.
Your class should typically implement Equals
and GetHashCode
as a means to distinguish class instances, and must implement this or the ==
operator (ideally both) if it is a value type.
Note, for value types the default Equals
behaviour is that of ValueType.Equals()
which if you look in Reflector (or read the MSDN description) uses reflection to compare the members of the two value instances.
The static Equals() method.
This is equivalent to return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB)))
where each type is converted to Object
for testing. My testing shows that overloaded comparison operators are ignored, but your Equals
method will be used if the objects are not null and aren't the same reference. As such, a.Equals(b)
does not necessarily equal object.Equals(a, b)
(for the cases where ((object)a) == ((object)b)
or either a or b is null).
The Equals method from IEquatable interface.
IEquatable provides a way for you to treat comparison to instances of the same class specially. Having said that your Equals
method should be handling the behaviour the same way:
If you implement Equals, you should
also override the base class
implementations of
Object.Equals(Object) and GetHashCode
so that their behavior is consistent
with that of the IEquatable.Equals
method
Nevertheless you should implement IEquatable:
To handle the possibility that objects
of a class will be stored in an array
or a generic collection object, it is
a good idea to implement IEquatable
so that the object can be easily
identified and manipulated.
The comparison operator ==
The comparison operator by default returns true when both of your objects are the same reference.
It is not recommended to override the comparison operator unless you are dealing with a value type (in which case it is recommended, along with the Equals
method) or an immutable reference type which you would usually compare by value (e.g. string
). Always implement !=
at the same time (in fact I get a requires a matching operator '!=' to also be defined
error if I do not).
Resources: