Просто чтобы добавить ответы выше:
Если вы не переопределяете Equals, то по умолчанию поведение сравнивается с ссылками на объекты. То же самое относится и к хэш-коду - имплементация по умолчанию обычно основана на адресе памяти ссылки.
Поскольку вы переопределили Equals, это означает, что правильное поведение - сравнивать то, что вы реализовали в Equals, а не в ссылках, поэтому вы должны сделать то же самое для хэш-кода.
Клиенты вашего класса будут ожидать, что хеш-код будет иметь аналогичную логику с методом equals, например, методы linq, которые используют IEqualityComparer, сначала сравнивают хеш-коды и только если они равны, они будут сравнивать метод Equals (), который может запускать дороже, если мы не реализовали хеш-код, равный объект, вероятно, будет иметь разные хеш-коды (потому что они имеют разные адреса памяти) и будет определен неправильно как не равный (Equals () даже не попадет).
Кроме того, кроме проблемы, что вы не сможете найти свой объект, если будете использовать его в словаре (потому что он был вставлен одним хеш-кодом, и при поиске его хеш-код по умолчанию, вероятно, будет другим, и снова Equals () даже не будет вызываться, как объясняет Марк Гравелл в своем ответе, вы также вводите нарушение концепции словаря или хэш-набора, которая не должна позволять идентичные ключи -
вы уже объявили, что эти объекты по сути одинаковы, когда вы переопределяете Equals, поэтому вы не хотите, чтобы оба они были разными ключами в структуре данных, которая предполагает наличие уникального ключа. Но поскольку у них другой хэш-код, «тот же» ключ будет вставлен как другой.