Rules 1 & 3 are contradictory to me.
To a certain extent, they are. The reason is simple: if an object is stored in a hash table and, by changing its value, you change its hash then the hash table has lost the value and you can't find it again by querying the hash table. It— It is therefore important that while objects are stored in a hash table, they retain their hash value.
To realizeensure this it is often simplest to make hashable objects immutable, thus evadingside-stepping the whole problem wholly. ItBut it is howeveractually sufficient to make only those fields immutable that determine the hash value.
Consider the following example:
struct Person { public readonly string FirstName; public readonly string Name; public readonly DateTime Birthday; public int ShoeSize; } People rarely change their birthdayname, and most people never changeeven less frequently their name (except when marrying)birthday. However, their shoe size may grow arbitrarily, or even shrink. It is therefore reasonable to identify people using their birthday and name but not their shoe size. The hash value should reflect this:
public override int GetHashCode() { return FirstNameHashCode.GetHashCodeCombine() ^FirstName, Name.GetHashCode() ^, Birthday.GetHashCode(); } And remember to override Equals whenever you override GetHashCode (and vice-versa)!