Nur um die obigen Antworten zu ergänzen:
Wenn Sie Equals nicht überschreiben, ist das Standardverhalten, dass Referenzen der Objekte verglichen werden. Dasselbe gilt für Hashcode - die Standard-Implmentierung basiert typischerweise auf einer Speicheradresse der Referenz. Da Sie Equals überschrieben haben, bedeutet dies, dass das korrekte Verhalten darin besteht, das zu vergleichen, was Sie auf Equals implementiert haben, und nicht die Referenzen, also sollten Sie dasselbe für den Hashcode tun.
Clients Ihrer Klasse werden erwarten, dass der Hashcode eine ähnliche Logik wie die equals-Methode hat, z.B. linq-Methoden, die einen IEqualityComparer verwenden, vergleichen zuerst die Hashcodes und nur wenn sie gleich sind, vergleichen sie die Equals()-Methode, die möglicherweise teurer ist, wenn wir den Hashcode nicht implementiert haben, werden gleiche Objekte wahrscheinlich unterschiedliche Hashcodes haben (weil sie unterschiedliche Speicheradressen haben) und werden fälschlicherweise als nicht gleich bestimmt (Equals() wird nicht einmal getroffen).
Abgesehen von dem Problem, dass Sie Ihr Objekt möglicherweise nicht finden können, wenn Sie es in einem Wörterbuch verwenden (weil es durch einen Hashcode eingefügt wurde und wenn Sie danach suchen, wird der Standard-Hashcode wahrscheinlich ein anderer sein und wiederum wird Equals() nicht einmal aufgerufen, wie Marc Gravell in seiner Antwort erklärt, führen Sie auch eine Verletzung des Wörterbuch- oder Hashset-Konzepts ein, das keine identischen Schlüssel zulassen sollte - Sie haben bereits deklariert, dass diese Objekte im Wesentlichen gleich sind, wenn Sie Equals überschreiben, also wollen Sie nicht, dass beide als unterschiedliche Schlüssel in einer Datenstruktur verwendet werden, die einen eindeutigen Schlüssel haben soll. Da sie aber einen unterschiedlichen Hashcode haben, wird der "gleiche" Schlüssel als ein anderer eingefügt.