Search code examples
c#pocoiequalitycompareriequatable

IEquatable on POCO identity field


I have POCOs from a SQL Server database that have an identity ID field. I would like to implement IEquatable so I can check if they're the same record, use .Contains() on List<T> etc.

Assuming I will never need to compare unsaved instances, is it sufficient to just implement using:

    public bool Equals(MyClass other)
    {
        return this.ID == other.ID;
    }

    public override int GetHashCode()
    {
        return this.ID;
    }

I'm about to do this, but just wanted to check that's fine, as I'm not 100% sure what GetHashCode has to do with it, or if there are any other considerations (such as the "unsaved instance" one, which I can discard) that I'm not aware of.


Solution

  • You need to override GetHashCode() whenever you override Equals() (which you should also do when you implement IEquatable<T>) so that classes that rely on it, such as Dictionary<TKey, TValue>, can handle it correctly. It's one of those inner details that annoyingly leaks out. More information.

    As for whether comparing your IDs is sufficient for determining equality, if you're absolutely sure that two entities with the same ID should be considered equivalent under all circumstances, then go for it. That's a question only the requirements of your application can answer. I've done it quite a few times myself, almost always with read-only entities.

    I would implement it this way:

    // IEquatable<MyClass> implementation
    public bool Equals(MyClass other) 
    {
      if (other == null) 
      {
        return false;
      }
    
      return this.ID == other.ID;
    }
    
    // Override of default Object.Equals()
    public override bool Equals(object other) 
    {
      return this.Equals(other as MyClass);
    }
    
    public override int GetHashCode()
    {
      // Call ID.GetHashCode() because ID may not always be int,
      // and the ID type might have a more useful implementation
      // of GetHashCode() to offer.
      return this.ID.GetHashCode(); 
    }
    

    You should probably also override the == and != operators in this case. You can always use Object.ReferenceEquals() if you want to distinguish between two distinct references with the same ID.