The equality pattern I like to see in C# is as follows:

For entity type classes

“Many objects are not fundamentally defined by their attributes, but rather by a thread of continuity and identity.” -Eric Evans

  1. /// <summary>
  2. /// Entity object where identity is based on identifier (e.g. Person)
  3. /// </summary>
  4. class Entity : IEquatable<Entity>
  5. {
  6. private readonly Int32 _Identifier;
  7. public Entity(Int32 identifier)
  8. {
  9. _Identifier = identifier;
  10. }
  11. public override bool Equals(object obj)
  12. {
  13. var result = Equals(obj as Entity);
  14. return result;
  15. }
  16. public override int GetHashCode()
  17. {
  18. var result = _Identifier.GetHashCode();
  19. return result;
  20. }
  21. public bool Equals(Entity other)
  22. {
  23. if (ReferenceEquals(other, null))
  24. return false;
  25. var result = _Identifier == other._Identifier;
  26. return result;
  27. }
  28. // optional operators
  29. public static Boolean operator ==(Entity target, Entity other)
  30. {
  31. if (ReferenceEquals(target, other))
  32. return true;
  33. if (ReferenceEquals(target, null))
  34. return false;
  35. var result = target.Equals(other);
  36. return result;
  37. }
  38. public static Boolean operator !=(Entity target, Entity other)
  39. {
  40. var result = !(target == other);
  41. return result;
  42. }
  43. }

For value type classes

“Many objects have no conceptual identity. These objects describe characteristics of a thing.” -Eric Evans

  1. /// <summary>
  2. /// Value object where identity is based on state (e.g. Money)
  3. /// </summary>
  4. class Value :IEquatable<Value>
  5. {
  6. private readonly Int32 _Property1, _Property2;
  7. public Value(Int32 property1, Int32 property2)
  8. {
  9. _Property1 = property1;
  10. _Property2 = property2;
  11. }
  12. public override bool Equals(object obj)
  13. {
  14. var result = Equals(obj as Value);
  15. return result;
  16. }
  17. public bool Equals(Value other)
  18. {
  19. if (ReferenceEquals(other, null))
  20. return false;
  21. var result =
  22. _Property1 == other._Property1 &&
  23. _Property2 == other._Property2;
  24. return result;
  25. }
  26. public override int GetHashCode()
  27. {
  28. var result =
  29. _Property1.GetHashCode() ^
  30. _Property2.GetHashCode();
  31. return result;
  32. }
  33. // optional operators
  34. public static Boolean operator == (Value target, Value other)
  35. {
  36. if (ReferenceEquals(target, other))
  37. return true;
  38. if (ReferenceEquals(target, null))
  39. return false;
  40. var result = target.Equals(other);
  41. return result;
  42. }
  43. public static Boolean operator !=(Value target, Value other)
  44. {
  45. var result = !(target == other);
  46. return result;
  47. }
  48. }