发表于: other | 作者: | 日期: 2013/8/07 12:08

前些天往一个自定义的类里面添加对比是否相同的方法,了解到C#可以用CompareTo,Equals和==这三种实现方式,equals()和==都是object自己就带的东西,而CompareTo则是需要继承IComparable接口,最后想了想,因为不熟悉,那些系统提供的方法还是少override为妙,就选了实现IComparable接口。
好了,那有了时间就该研究下:
参考一下MSDN:点击跳转Equals() 和运算符 == 的重写准则
从这上面可以看到,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函数应有的作用。
MSDN上Equals函数实现的保证:
Equals 的新实现应该遵循 Equals 的所有保证:
x.Equals(x) 返回 true。
x.Equals(y) 与 y.Equals(x) 返回相同的值。
如果 (x.Equals(y) && y.Equals(z)) 返回 true,则 x.Equals(z) 返回 true。
只要不修改 x 和 y 所引用的对象,x.Equals(y) 的后续调用就返回相同的值。
x.Equals (null) 返回 false(仅非空值类型。有关更多信息,请参见可空类型(C# 编程指南)。)
由此看来,对于之前我的需求:比较两个自定义类的内容是否相同,还是应该重写Equals(Object),并建议重载对自己的类的实现Equals(MyClass)。
而对于==运算符的解释为:拖过判断两个引用是否指示同一对象来测试是否相等。也就是引用相等了,可对于上面对string的测试,RefrenceEquals为False时,==却返回的True,这是因为还有这么一条:当类型不可变(即实例中包含的数据不可更改)时,通过重载运算符== 来比较值是否相等而不是比较引用是否相等可能会很有用。(这里和java不同,java的==就是用来比较引用是否相等的,而且java也不允许算符重载)。
我们大部分情况下写的自定义类都是可变的,所以一般用不到也不应该对==进行重载。
再来看看IComparable接口
参考MSDN:点击跳转IComparable 接口
它的作用为:定义一种特定于类型的通用比较方法,值类型或类通过实现此方法对其实力进行排序。就是说它主要是在对大小的比较,或为包含在列表中时的排序功能而用的。如果MyClass实现了IComparable接口之后,对于List就可以使用排序功能(Sort函数)。
由上面看,Equals函数主要用于通过对比自定义类中的每个成员来对比两个类是否值相等;==算符则是比较是否引用相等,不建议重写;IComparable则通过对比类中一个或几个成员(如时间,序号等)来判断大小从而进行排序。
[整理自网络]

: https://blog.darkmi.com/2013/08/07/858.html

本文相关评论 - 1条评论都没有呢
Post a comment now » 本文目前不可评论

No comments yet.

Sorry, the comment form is closed at this time.