System.Object类型提供了一个Equals的虚方法,其目的为判断两个对象是否有个相同的"值".
1 class Object
2 {
3 public virtual Boolean Equals(Object obj)
4 {
5 //如果两个引用指向的是同一个对象
6 //它们肯定相等
7 if(this==obj)
8 {
9 return (true);
10 }
11
12 return (false);
13
14 }
15 }
这也许是最简单的方法.
但有时间,它提供的默认实现对我们来说是不够的,必须重写Equals方法.
自己写的时候,要遵循以下4条规则:
1.Equals方法必须是自反的.也就是说,x.Equals(x)必须返回true.
2. Equals方法必须是对称的.也就是说,x.Equals(y)和y.Equals(x)必须返回同样的值.
3.Equals方法必须是可传递的.也就是说,如果x.Equals(y)和y.Equals(z)都返回true,那么x.Equals(z)也必须返回 true.
4. Equals方法必须是前后一致的.也就是说,如果两个对象的值没有发生变化,多次调用Equals方法的返回值应该相同.
(一)为基类没有重写Object.Equals方法的引用类型实现Equals
class MyRefType:BaseType
{
RefType refobj; //引用类型
ValueType valobj; //值类型
public override bool Equals(object obj)
{
//因为‘this’不为null,所以如果obj为null
//那么两个对象将不可能相等
if (obj == null)
return false;
//如果两个对象的类型不同,那么它们不可能相等
if (this.GetType() != obj.GetType())
return false;
//将obj转型为定义的类型以访问其中的字段,这里的
//转型不会失败,因为已经知道两个对象是同一类型
MyRefType other=(MyRefType)obj;
//比较其中的引用类型字段
if (!Object.Equals(refobj, other.refobj))
return false;
//比较其中的值类型字段
if (!valobj.Equals(other.valobj))
return false;
return true; //到这里两个对象才相等
}
}
这要注意的:
1.要比较引用类型的字段,我们应该调用Object的静态方法Equals方法.
Objext的静态方法Equals方法是一个比较两个引用类型对象的辅助方法.采用这种方法比较,是因为即使两个字段出现了值为null的情况,代码仍会正常运行.
2.要比较值类型的字段,应该调用该字段类型的Equals方法.不应该调用Object的静态方法Equals方法.因为值类型对象的值永远不可能为null,并且调用Object的静态方法Equals会对值类型对象执行装箱操作.
(二)为基类重写了Object.Equals方法的引用类型实现Equals
class MyRefType:BaseType
{
RefType refobj; //引用类型
ValueType valobj; //值类型
public override bool Equals(object obj)
{
//首先让基类型比较其中的字段
if (!base.Equals(obj))
return false;
//因为‘this’不为null,所以如果obj为null
//那么两个对象将不可能相等
if (obj == null)
return false;
//如果两个对象的类型不同,那么它们不可能相等
if (this.GetType() != obj.GetType())
return false;
//将obj转型为定义的类型以访问其中的字段,这里的
//转型不会失败,因为已经知道两个对象是同一类型
MyRefType other=(MyRefType)obj;
//比较其中的引用类型字段
if (!Object.Equals(refobj, other.refobj))
return false;
//比较其中的值类型字段
if (!valobj.Equals(other.valobj))
return false;
return true; //到这里两个对象才相等
}
}
如果调用base.Equals会导致调用Object.Equals方法,那么就不应该再调用它.这一点很重要.因为只有在两个引用指向同一个对象时,Object.Equals方法才会返回true.如果两个引用没有指向同一个对象,那么它将返回false.这样我们实现的Equals方法将总是返回false.
当然,如果我们定义的类型直接继承自Object,我们就应该象第一段代码那样来实现Equals.如果我们定义的类型不是直接继承自Object,我们必须首先确定该类型的基类型是否重写了Equals方法.如果其中任何一个基类型重写了Equals方法,那么我们就应该象这段代码先base.Equals方法.