Why must you override GetHashCode whenever you override Equals?
Quick Answer
The contract: if two objects are Equals, they must return the same GetHashCode. Hash-based collections (Dictionary, HashSet) first bucket by hash code, then check equality within the bucket. Override Equals without GetHashCode and equal objects land in different buckets, so lookups silently fail.
Because hash-based collections rely on the invariant that equal objects have equal hash codes. When you put something in a Dictionary or HashSet, it computes the hash code to pick a bucket, and on lookup it does the same and then compares with Equals inside that bucket. If I override Equals to say two orders with the same id are equal but leave GetHashCode as the default identity hash, the two equal orders get different buckets and the collection never finds the match. I build the hash from the same fields Equals uses, with HashCode.Combine, and those fields must be immutable. Records do all this automatically.
- Use
HashCode.Combine(a, b, c)to build one from the same fieldsEqualscompares. - Only include fields that don't change while the object is a key — a mutable key is a bug waiting to happen.
- Unequal objects may share a hash code (collision) — that's allowed, just slower.
recordtypes generate both correctly for you based on all properties.