在非不可变类型中重载 == 运算符

6
MSDN对重载Equals()和Operator==的指导方针中提到:

默认情况下,operator ==通过确定两个引用是否指向同一个对象来测试引用相等性,因此引用类型不需要实现operator ==即可获得此功能。当类型被声明为不可变时,意味着实例中包含的数据不能被更改,在这种情况下,重载operator ==以比较值相等性而不是引用相等性可能很有用,因为作为不可变对象,只要它们具有相同的值,它们就可以被认为是相同的。在不可变类型之外覆盖operator ==是不推荐的。

有人能解释一下为什么会出现加粗的内容吗?

编辑 - 此指南是否仅适用于==操作符,还是也适用于Equals方法?

2个回答

16

我的猜测是,让事物的操作方式类似于 .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
假设您有一个可变类型A,并创建了一个类型A的对象集合。如果该对象已经存在于集合中,则向集合添加对象应失败。
现在假设您将一个对象添加到集合中,然后更改其属性,使其等于集合中的另一个对象。您已经创建了一个非法状态,在该状态下,集合中存在两个相等的对象。

但是使用Equals而不是==不能解决这个问题。 - Billy ONeal
另一个指导方针是总是一起重写 ==Equals() 。还有 getHashCode() - H H
实际上是有区别的 - "Equal"在语义上与"=="不同。阅读两者的文档以了解差异。 - TomTom
@TomTom:但是Set使用Equals而不是==进行比较,因此关于Set变得不一致的论点仍然存在。 - Billy ONeal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接