覆盖非不可变类型中的==运算符

时间:2010-12-28 14:22:05

标签: c# .net operator-overloading immutability equality

MSDN Guidelines for Overloading Equals() and Operator ==州:

  

默认情况下,运算符==测试   通过确定是否引用相等   两个参考文献表明相同   对象,因此不需要引用类型   为了实现operator ==   获得此功能。当一种类型   是不可变的,意思是数据   实例中包含的内容不能   更改,重载operator ==   比较值相等而不是   引用相等可能很有用   因为,作为不可变对象,他们   可以认为是相同的   它们具有相同的价值。的重写   operator ==在非不可变类型中   不推荐。

任何人都可以解释粗体背后的推理吗?

编辑 - 此外,此指南仅与==运算符相关,还是仅适用于Equals方法?

2 个答案:

答案 0 :(得分: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准则,则遵循重要类(如字符串)所采用的准则。基本上 - 如果使用==的比较成功,程序员就知道该比较将始终成功,只要涉及的引用不会被分配给新对象。程序员不必担心对象的内容不同,因为它们永远不会有所不同:

//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.

归结为指南没有真正的技术原因 - 它只是与框架中的其他类保持一致。

答案 1 :(得分:0)

假设您有一个可变类型A并且您创建了一个或多个类型的对象。如果该对象已存在于该集合中,则该对象将失败。

现在假设您向对象添加一个对象,然后更改其属性,使其等于集合中的另一个对象。您创建了一个非法状态,其中集合中有两个相等的对象。