Я прочитал около 10 различных вопросов о том, когда и как переопределить GetHashCode
, но есть еще кое-что, что я не совсем понимаю. Большинство реализаций GetHashCode
основаны на хэш-кодах полей объекта, но указывалось, что значение GetHashCode
никогда не должно изменяться в течение срока службы объекта. Как это работает, если поля, на которых он основан, являются изменяемыми? Кроме того, что если я хочу, чтобы поиск по словарю и т. Д. Основывался на равенстве ссылок, а не на моем переопределенном Equals
?
Я в первую очередь переопределяю Equals
для простоты модульного тестирования моего кода сериализации, который я предполагаю, что сериализация и десериализация (к XML в моем случае) убивает ссылочное равенство, поэтому я хочу убедиться, что по крайней мере это правильно по равенству значений , Это плохая практика переопределять Equals
в этом случае? В основном в большинстве исполняемого кода я хочу ссылочного равенства и всегда использую ==
, и я не переопределяю это. Должен ли я просто создать новый метод ValueEquals
или что-то вместо переопределения Equals
? Раньше я предполагал, что фреймворк всегда использует ==
, а не Equals
для сравнения, и поэтому я подумал, что было бы безопасно переопределить Equals
, так как мне показалось, что его целью было, если вы хотите иметь 2-е определение равенства, который отличается от оператора ==
. Из чтения нескольких других вопросов, хотя кажется, что это не так.
EDIT:
Кажется, мои намерения были неясны, я имею в виду, что в 99% случаев я хочу получить простое ссылочное равенство, поведение по умолчанию, никаких сюрпризов. В очень редких случаях я хочу иметь равенство значений и явно запрашивать равенство значений, используя .Equals
вместо ==
.
Когда я делаю это, компилятор также рекомендует переопределить GetHashCode
, и вот как возник этот вопрос. Казалось, что для GetHashCode
существуют противоречивые цели применительно к изменяемым объектам:
- Если
a.Equals(b)
, то a.GetHashCode()
должно == b.GetHashCode()
.
- Значение
a.GetHashCode()
никогда не должно изменяться в течение срока службы a
.
Это кажется естественным противоречием, когда изменяемый объект, потому что, если состояние объекта изменяется, мы ожидаем, что значение .Equals()
изменится, что означает, что GetHashCode
должен измениться, чтобы соответствовать изменению в .Equals()
, но GetHashCode
не должно меняться.
Почему, кажется, существует это противоречие? Разве эти рекомендации не предназначены для применения к изменчивым объектам? Возможно, предполагается, но, возможно, стоит упомянуть, что я имею в виду классы, а не структуры.
Разрешение:
Я отмечаю JaredPar как принятый, но в основном для взаимодействия с комментариями. Подводя итог, я понял из этого, что единственный способ достичь всех целей и избежать возможного странного поведения в крайних случаях - это переопределить только Equals
и GetHashCode
на основе неизменяемых полей или реализовать IEquatable
. Похоже, что этот вид уменьшает полезность переопределения Equals
для ссылочных типов, поскольку, как я видел, большинство ссылочных типов обычно не имеют неизменяемых полей, если они не хранятся в реляционной базе данных для идентификации их с их первичными ключами.