Care must be taken when overloading the equality (==) operator. In this case, a standard comparison of either object being passed to the overloaded operator with null, ie.
if (object == null) ...
will cause an infinite loop to be created at run-time and an overflow exception will be thrown whenever the method is called. To avoid this whilst not upsetting FxCop, use ReferenceEquals to compare the two items for reference equality first, then to compare each operand with null, returning true when both operands are null and false when only one operand is null. Finally perform the comparison of properties that determines whether the two parameters are functionality equal.
This example comes from the BusinessObject base class of my business framework. The Reference property is used to determine euality of two business objects. Note that the first check for reference equality correctly identifies if both items are null meaning my earlier revision to this comment was unnecessary:
[C#]
/// <summary>
/// Compares two business objects for equality.
/// </summary>
/// <param name="object1">The first business object.</param>
/// <param name="object2">The second business object.</param>
/// <returns>True if the business objects are the same.</returns>
public static bool operator ==(BusinessObject object1, BusinessObject object2)
{
if (Object.ReferenceEquals(object1, object2)) return true;
if (Object.ReferenceEquals(object1, null)) return false;
if (Object.ReferenceEquals(object2, null)) return false;
return object1.Reference == object2.Reference;
}
/// <summary>
/// Compares two business objects for inequality.
/// </summary>
/// <param name="object1">The first business object.</param>
/// <param name="object2">The second business object.</param>
/// <returns>True if the business objects are different.</returns>
public static bool operator !=(BusinessObject object1, BusinessObject object2)
{
// Validate
if (Object.ReferenceEquals(object1, object2)) return false;
if (Object.ReferenceEquals(object1, null)) return true;
if (Object.ReferenceEquals(object2, null)) return true;
return object1.Reference != object2.Reference;
}
As the equality operator is overloaded, so should be the Equals method and the GetHashCode method. In the Equals method there is no requirement to compare null against null as the current object cannot be null.
[C#]
/// <summary>
/// Compares the business object with a second business object.
/// </summary>
/// <param name="obj">The business object to compare with.</param>
/// <returns>True if the business objects are the same.</returns>
public override bool Equals(object obj)
{
// Validate
if (obj == null) return false;
return _reference == ((BusinessObject)obj).Reference;
}
/// <summary>
/// Generates a hash code for the business object;
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return _reference.GetHashCode();
}