C#中的相等有两种类型:引用相等(ReferenceEquals)和值相等(Equals)。值相等就是说两个对象包含相同的值。而引用相等则比较的是两个对象的引用是否是同一个对象。也就是说,如果ReferenceEquals为True,则Equals必然为True,反过来就不一定了。
这样的话可以看出来,ReferenceEquals我们没有比较去管他什么,系统自动解决,object类实现的静态RefrenceEquals函数就够了。而对于自定义的类型的话,如果想要实现判断值相等,是需要重写Equals函数的。
我们可以看一下string和自定义类的对比:
string strA = "Hello";
string strB = string.Copy(strA);
Console.WriteLine(strA == strB); //True
Console.WriteLine(strA.Equals(strB)); //True
Console.WriteLine(object.Equals(strA, strB)); //True
Console.WriteLine(object.ReferenceEquals(strA, strB)); //False
class MyClass
{
public int value = 1;
}
...
MyClass oA = new MyClass();
MyClass oB = new MyClass();
Console.WriteLine(oA == oB); //False
Console.WriteLine(oA.Equals(oB)); //False
Console.WriteLine(object.Equals(oA, oB)); //False
Console.WriteLine(object.ReferenceEquals(oA, oB)); //False
先不考虑==号,看几个Equals的表现,Equals是要实现值相等比较的效果的,.net 在实现string的时候就重写了Equals(object) ,并添加重载函数Equals(string) ,因此两个比较才会返回True。而不实现这两个函数的后果就是都返回False,无法符合Equals函数应有的作用。
由此看来,对于之前我的需求:比较两个自定义类的内容是否相同,还是应该重写Equals(Object),并建议重载对自己的类的实现Equals(MyClass)。
而对于==运算符的解释为:通过过判断两个引用是否指示同一对象来测试是否相等。也就是引用相等了,可对于上面对string的测试,RefrenceEquals为False时,==却返回的True,这是因为还有这么一条:当类型不可变(即实例中包含的数据不可更改)时,通过重载运算符== 来比较值是否相等而不是比较引用是否相等可能会很有用。
我们大部分情况下写的自定义类都是可变的,所以一般用不到也不应该对==进行重载。