Friday, September 20, 2024

Overload Operators the Right Way in C#

It’s a good rule of thumb to overload the equality operators on classes.

That ensures a correct comparison between to class instances of the same type. If you don’t, .NET automatically uses reflection and that is way slower than a custom implementation.

We all use the equality operators (“==”, “!=”) all the time and we expect them to be right every time. They are not!, but even if they were there is a good chance that you want to change them anyway. For instance, if your class has a unique Id property, then that property is the one that tells if two instances are the same. If you don’t overload the operators, you could have two instances with the same Id treated as two different instances.

First of all, you have to find out what makes two instances different. Let’s keep using the Id property example in an imaginary class called Foo. Then lets start overriding the GetHashCode() method so it returns the hashcode of the Id property.

/// <summary>
/// A uniquely key to identify this particullar instance of the class
/// </summary>
/// <returns>A unique integer value</returns>
public override int GetHashCode()
{
  return this.Id.GetHashCode();
}

Whenever the GetHashCode() method is called, it returns a unique integer value that represents the uniqueness of the class instance. Now we can use that method to overload the operators.

/// <summary>
/// Checks to see if two business objects are the same.
/// </summary>
public static bool operator ==(Foo first, Foo second)
{
  // Checks if the pointer in memory is the same
  if (Object.ReferenceEquals(first, second))
  {
   return true;
  }

  // Checks for null values
  if ((object)first == null || (object)second == null)
  {
   return false;
  }

  return first.GetHashCode() == second.GetHashCode();
}

/// <summary>
/// Checks to see if two business objects are different.
/// </summary>
public static bool operator !=(Foo first, Foo second)
{
  return !(first == second);
}

The reason why it is necessary to box the two Foo parameters (first, second) to type object, is to avoid an overflow exception.

We still need one more thing to be sure that we can compare two instances to each other, and that is by overriding the Equals() method. You can use the Equals() method or the operators to compare instances and they should always return the same result.

/// <summary>
/// Comapares this object with another
/// </summary>
/// <param name="obj">The object to compare</param>
/// <returns>True if the two objects as equal</returns>
public override bool Equals(object obj)
{
  if (obj == null)
  {
   return false;
  }

  if (obj.GetType() == this.GetType())
  {
   return obj.GetHashCode() == this.GetHashCode();
  }

  return false;
}

You can implement these methods on a base class so you won’t have to write it on all the derived classes. Because these methods uses GetHashCode() to compare two instances, it would be preferable to override that method in the derived classes if needed.

Comments

Tag:

Add to Del.icio.us | Digg | Reddit | Furl

Bookmark murdok:

Mads Kristensen currently works as a Senior Developer at Traceworks located
in Copenhagen, Denmark. Mads graduated from Copenhagen Technical Academy with a multimedia degree in
2003, but has been a professional developer since 2000. His main focus is on ASP.NET but is responsible for Winforms, Windows- and
web services in his daily work as well. A true .NET developer with great passion for the simple solution.

Home

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles