Как уже говорили другие, использование Reflection in Equals кажется хитрым. Оставляя это в стороне, давайте сосредоточимся на GetHashCode.
Основное правило для GetHashCode, которое вы не должны нарушать, это , если два объекта равны, то они оба должны иметь одинаковый хэш-код . Или эквивалентный способ сказать, что это , если два объекта имеют разные хеш-коды, тогда они должны быть неравны. Ваша реализация там выглядит хорошо.
Вы можете нарушать обратное. То есть, если два объекта имеют одинаковый хэш-код, им разрешается быть равными или неравными, как вы считаете нужным.
Я предполагаю, что "Id" является неизменным свойством. Если «Id» может меняться в течение всего времени жизни объекта, тогда у вас могут возникнуть проблемы при помещении объекта в хеш-таблицу. Подумайте о том, чтобы при вычислении равенства и хеш-кода использовались только неизменяемые свойства.
Ваша реализация выглядит хорошо, но тот факт, что вы задаете вопрос, указывает на то, что вы можете не иметь четкого представления обо всех тонких факторах, влияющих на реализацию реализации GetHashCode. Хорошее место для начала - моя статья на эту тему:
http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/