Переопределение оператора == в неизменяемых типах - PullRequest
6 голосов
/ 28 декабря 2010

* * * * * Состояние:

По умолчанию оператор == проверяет равенство ссылок, определяя, указывают ли две ссылки натот же объект, поэтому ссылочные типы не должны реализовывать operator == для получения этой функциональности.Когда тип является неизменяемым, то есть данные, содержащиеся в экземпляре, не могут быть изменены, может быть полезен оператор перегрузки == для сравнения равенства значений вместо ссылочного равенства, поскольку в качестве неизменяемых объектов их можно считать одинаковыми, если они имеюттакое же значение. Переопределение оператора == в неизменяемых типах не рекомендуется.

Может кто-нибудь объяснить причину, стоящую за жирным шрифтом?

РЕДАКТИРОВАТЬ - Кроме того, относится ли это руководство только к оператору == или оно предназначено также для метода Equals?

Ответы [ 2 ]

16 голосов
/ 28 декабря 2010

Мое обоснованное предположение состояло бы в том, чтобы заставить вещи работать как встроенные типы в .NET, а именно, что == должно работать как ссылочное равенство, где это возможно, и что Equals должен работать как равенство значений, где это возможно. Рассмотрим фактическую разницу между == и Equals:

object myObj = new Integer(4);
object myObj2 = new Integer(4);

//Note that == is only called if the ref'd objects are cast as a type
//overloading it.
myObj == myObj2; //False (???)
myObj.Equals(myObj2); //True (This call is virtual)

//Set the references equal to each other -- note that the operator==
//comparison now works.
myObj2 = myObj;
myObj == myObj2; //True
myObj.Equals(myObj2); //True

Такое поведение, конечно, противоречиво и сбивает с толку, особенно для новых программистов - но оно демонстрирует разницу между сравнениями ссылок и сравнений значений.

Если вы следуете этому руководству MSDN, вы следуете руководству, принятому важными классами, такими как string. По сути - если сравнение с использованием == завершается успешно, программист знает, что это сравнение всегда будет успешным, пока соответствующие ссылки не будут присвоены новым объектам. Программисту не нужно беспокоиться о том, что содержимое объектов различно, потому что они никогда не будут разными:

//Mutable type
var mutable1 = new Mutable(1);
var mutable2 = mutable1;
mutable1 == mutable2; //true
mutable1.MutateToSomethingElse(56);
mutable1 == mutable2; //still true, even after modification
//This is consistent with the framework. (Because the references are the same,
//reference and value equality are the same.) Consider if == were overloaded,
//and there was a difference between reference and value equality:

var mutable1 = new Mutable(1);
var mutable2 = new Mutable(1);
mutable1 == mutable2; //true
mutable1.MutateToSomethingElse(56);
mutable1 == mutable2; //oops -- not true anymore
//This is inconsistent with, say, "string", because it cannot mutate.

Это сводится к тому, что для руководства нет никакой реальной технической причины - это просто для соответствия остальным классам в фреймворке.

0 голосов
/ 28 декабря 2010

Предположим, у вас есть изменяемый тип A, и вы создаете набор или объекты типа A. Добавление объекта в набор должно завершиться неудачей, если этот объект уже существует в наборе.

Теперь, допустим, вы добавилиобъект в набор, а затем вы изменяете его свойства, чтобы он стал равным другому объекту в наборе.Вы создали недопустимое состояние, в котором в наборе есть два равных объекта.

...