C# › Equality: Equals, GetHashCode & IEquatable

How should Equals() be implemented differently for a class designed to support INHERITANCE, to correctly handle equality between a base type and derived types?

Advanced

Answer

A careful Equals() implementation for an inheritance hierarchy typically checks `GetType() == other.GetType()` (not just 'is BaseType') to prevent a base and derived instance with otherwise-matching fields from incorrectly comparing as equal — since a derived type may add fields that the base's Equals() logic isn't aware of, treating them as equal could violate the type's actual semantic identity.
public class Shape {
  public override bool Equals(object? obj) =>
    obj != null && GetType() == obj.GetType() && EqualsCore((Shape)obj); // exact type match required
  protected virtual bool EqualsCore(Shape other) => true;
}
public class Circle : Shape {
  public double Radius;
  protected override bool EqualsCore(Shape other) => other is Circle c && Radius == c.Radius;
}
Real-world example Correctly implementing equality across a class hierarchy where a base Shape and a derived Circle should never accidentally compare as equal.

Common follow-ups: What subtle bug can occur if you use 'is BaseType' instead of an exact GetType() check in this scenario?