Я обычно разрабатываю свои доменные модели, когда ==
и ReferenceEquals()
выполняют равенство ссылок.И Equals()
выполняет значение равенства.Причина, по которой я не использую ни один из них для равенства идентичности, имеет три причины:
Не все имеют идентичность , поэтому может возникнуть путаница в отношении того, как Equals () и == действительно работают, когда объектбез идентичности участвует.Подумайте, например, о кеше, содержащем несколько объектов или временных / вспомогательных объектов.Как насчет агрегированных объектов, которые могут быть основаны на нескольких разных объектах домена?Какую идентичность она будет сравнивать?
Равенство идентичности - это подмножество равенства значений , из моего опыта, когда речь идет о равенстве идентичности, равенство значений не сильно отстает, и обычно ценность идентичности включает в себя равенство идентичности, а также,В конце концов, если идентичности не одинаковы, действительно ли значения одинаковы?
Что само по себе равенство идентичности действительно говорит , задайте себе вопрос: «Что означает равенство идентичности?без контекста?Является ли пользователь с Id 1 равным комментарию с Id 1?Я, конечно, надеюсь, что нет, поскольку обе сущности очень разные вещи
Так зачем использовать какой-либо из встроенных методов равенства (==
и Equals()
) для чего-то, что является исключением, а не правилом?Вместо этого я стремлюсь реализовать базовый класс, который предоставляет мою идентификационную информацию и реализует равенство идентичности в зависимости от того, насколько распространено равенство идентичности в моем текущем домене.
Например;в домене, где равенство идентичностей встречается редко, я бы создал пользовательский EqualityComparer<T>
для выполнения идентичности, когда и где это необходимо, с учетом контекста, если равенство идентичностей не является общей проблемой в моем текущем домене.
Однако, в области, где равенство идентичностей очень распространено, я бы вместо этого выбрал метод в моем базовом классе идентичности, называемый IdentityEquals()
, который заботится о равенстве идентичности на базовом уровне.
Таким образом, я раскрываю равенство идентичности только там, где оно уместно и логично.Без какой-либо потенциальной путаницы о том, как может сработать любая из моих проверок на равенство.Будь то Equals()
, ==
или IdentityEquals
/ EqualityComparer<T>
(в зависимости от того, насколько распространено равенство идентичностей в моем домене).
Также в качестве дополнительного примечания я бы рекомендовал прочесть * 1034 от Microsoft* рекомендации по перегрузке равенства .
В частности:
По умолчанию оператор == проверяет равенство ссылок, определяя, указывают ли две ссылки на один и тот же объект, поэтому ссылочные типы не должны реализовывать оператор == вДля того, чтобы получить эту функциональность.Когда тип является неизменяемым, то есть данные, содержащиеся в экземпляре, не могут быть изменены, может быть полезен оператор перегрузки == для сравнения равенства значений вместо ссылочного равенства, поскольку в качестве неизменяемых объектов их можно считать одинаковыми, если они имеюттакое же значение. Переопределение оператора == в неизменяемых типах не рекомендуется.
РЕДАКТИРОВАТЬ:
Относительно Assert.AreEqual
и Assert.AreSame
ваш домен определяет, что означает равенство;будь то ссылка, личность или ценность.Таким образом, ваше определение Equals
в вашем домене также распространяется на определение Assert.AreEqual
.Если вы скажете, что Equals
проверяет равенство идентичности, то логическим расширением Assert.AreEqual
проверяет равенство идентичности.
Assert.AreSame
проверяет, являются ли оба объекта одним и тем же объектом.Одинаковые и равные две разные концепции.Единственный способ проверить, является ли объект, на который ссылается A, таким же, как объект, на который ссылается B, - это ссылочное равенство.Семантически и синтаксически оба названия имеют смысл.