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