先看一下Object类的Equals方法的实现:
public static bool Equals(object objA, object objB)
{
if (objA == objB)//如果两个对象的引用相同,都指向同一个对象那么肯定是相等
{
return true;
}
if ((objA != null) && (objB != null))//如果两个对象之一为null 那么肯定不相当
{
return objA.Equals(objB);
}
return false;
}
public virtual Boolean Equals(Object obj)
{
if(this == obj) return true;//如果两个对象的引用相同,都指向同一个对象那么肯定是相等
return false;
}
{
if (objA == objB)//如果两个对象的引用相同,都指向同一个对象那么肯定是相等
{
return true;
}
if ((objA != null) && (objB != null))//如果两个对象之一为null 那么肯定不相当
{
return objA.Equals(objB);
}
return false;
}
public virtual Boolean Equals(Object obj)
{
if(this == obj) return true;//如果两个对象的引用相同,都指向同一个对象那么肯定是相等
return false;
}
在设计类型的时候可以分3种情况:
1、我们当前所设计的引用类的基类型如果没有重写Object的Equals方法而是直接继承得来,那么实现Equals方法可以这样:
class MyRefType : BaseType
{
RefType refobj;
ValType valobj;
public override Boolean Equals(Object obj)
{
if(obj == null) return false;//当前对象this不可能为null,所以如果obj为null,那么肯定不相等
if(this.GetType() != obj.GetType()) return false;//如果连类型都不同,那么肯定不相同啦
MyRefType other = (MyRefType)obj;//因为类型已经可以肯定相同,转换安全
if(!Object.Equals(refobj,other.refobj)) return false;//比较引用类型字段,这里只有用Object的静态方法Equals来比较,为什么?刚才看了Object的静态方法实现,其中是使用比较对象之一的实例方法Equals来比较的,而我们现在正在这个类型的实例方法Equals中,这样会不会引起循环引用?
if(!valobj.Equals(other.valobj)) return false;//比较值类型字段
return true;//到这里两个对象才相同
}
public static Boolean operator==(MyRefType o1, MyRefType o2)
{
return Object.Equals(o1,o2);
}
public static Boolean operator!=(MyRefType o1,MyRefType o2)
{
return !(o1 == o2);
}
}
{
RefType refobj;
ValType valobj;
public override Boolean Equals(Object obj)
{
if(obj == null) return false;//当前对象this不可能为null,所以如果obj为null,那么肯定不相等
if(this.GetType() != obj.GetType()) return false;//如果连类型都不同,那么肯定不相同啦
MyRefType other = (MyRefType)obj;//因为类型已经可以肯定相同,转换安全
if(!Object.Equals(refobj,other.refobj)) return false;//比较引用类型字段,这里只有用Object的静态方法Equals来比较,为什么?刚才看了Object的静态方法实现,其中是使用比较对象之一的实例方法Equals来比较的,而我们现在正在这个类型的实例方法Equals中,这样会不会引起循环引用?
if(!valobj.Equals(other.valobj)) return false;//比较值类型字段
return true;//到这里两个对象才相同
}
public static Boolean operator==(MyRefType o1, MyRefType o2)
{
return Object.Equals(o1,o2);
}
public static Boolean operator!=(MyRefType o1,MyRefType o2)
{
return !(o1 == o2);
}
}
我们从Object类的静态Equals方法的实现可以看出实现Equals方法时,只要实现当前类型的实例方法Equals就可以了,静态方法就可以免了,直接调用Object类的静态Equals方法即可,因为最终比较还是要使用这个子类的实例方法。
2、我们当前所设计的引用类的基类型如果重写了Object的Equals方法,那么实现Equals方法可以这样:
class MyRefType : BaseType
{
RefType refobj;
ValType valobj;
public override Boolean Equals(Object obj)
{
if(!base.Equals(obj)) return false; //如果连基类型都认为对象不相等,那么就不可能相等
if(obj == null) return false;//当前对象this不可能为null,所以如果obj为null,那么肯定不相等
if(this.GetType() != obj.GetType()) return false;//如果连类型都不同,那么肯定不相同啦
MyRefType other = (MyRefType)obj;//因为类型已经可以肯定相同,转换安全
if(!Object.Equals(refobj,other.refobj)) return false;//比较引用类型字段,这里只有用Object的静态方法Equals来比较,为什么?刚才看了Object的静态方法实现,其中是使用比较对象之一的实例方法Equals来比较的,而我们现在正在这个类型的实例方法Equals中,这样会不会引起循环引用?
if(!valobj.Equals(other.valobj)) return false;//比较值类型字段
return true;//到这里两个对象才相同
}
public static Boolean operator==(MyRefType o1, MyRefType o2)
{
return Object.Equals(o1,o2);
}
public static Boolean operator!=(MyRefType o1,MyRefType o2)
{
return !(o1 == o2);
}
}
{
RefType refobj;
ValType valobj;
public override Boolean Equals(Object obj)
{
if(!base.Equals(obj)) return false; //如果连基类型都认为对象不相等,那么就不可能相等
if(obj == null) return false;//当前对象this不可能为null,所以如果obj为null,那么肯定不相等
if(this.GetType() != obj.GetType()) return false;//如果连类型都不同,那么肯定不相同啦
MyRefType other = (MyRefType)obj;//因为类型已经可以肯定相同,转换安全
if(!Object.Equals(refobj,other.refobj)) return false;//比较引用类型字段,这里只有用Object的静态方法Equals来比较,为什么?刚才看了Object的静态方法实现,其中是使用比较对象之一的实例方法Equals来比较的,而我们现在正在这个类型的实例方法Equals中,这样会不会引起循环引用?
if(!valobj.Equals(other.valobj)) return false;//比较值类型字段
return true;//到这里两个对象才相同
}
public static Boolean operator==(MyRefType o1, MyRefType o2)
{
return Object.Equals(o1,o2);
}
public static Boolean operator!=(MyRefType o1,MyRefType o2)
{
return !(o1 == o2);
}
}
注意当基类按照自己的逻辑重写Object的Equals方法,那么必须先调用基类的Equals方法来判断,否则我们的Equals实现可能总是先判断两个对象的引用是否相同,这样可能大部分情况下都是永远返回false。
3、为值类型实现Equals方法:
先看看System.ValueType的Equals方法的实现:
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
RuntimeType type1 = (RuntimeType) base.GetType();//获取运行时类型
RuntimeType type2 = (RuntimeType) obj.GetType();
if (type2 != type1)//类型都不同,就没有机会相等
{
return false;
}
object obj1 = this;
if (ValueType.CanCompareBits(this))
{
return ValueType.FastEqualsCheck(obj1, obj);
}
FieldInfo[] infoArray1 = type1.InternalGetFields(BindingFlags.NonPublic | (BindingFlags.Public | BindingFlags.Instance), false);
for (int num1 = 0; num1 < infoArray1.Length; num1++)//比较每个字段的值
{
object obj2 = ((RuntimeFieldInfo) infoArray1[num1]).InternalGetValue(obj1, false);
object obj3 = ((RuntimeFieldInfo) infoArray1[num1]).InternalGetValue(obj, false);
if (obj2 == null)
{
if (obj3 != null)
{
return false;
}
}
else if (!obj2.Equals(obj3))
{
return false;
}
}
return true;
}
{
if (obj == null)
{
return false;
}
RuntimeType type1 = (RuntimeType) base.GetType();//获取运行时类型
RuntimeType type2 = (RuntimeType) obj.GetType();
if (type2 != type1)//类型都不同,就没有机会相等
{
return false;
}
object obj1 = this;
if (ValueType.CanCompareBits(this))
{
return ValueType.FastEqualsCheck(obj1, obj);
}
FieldInfo[] infoArray1 = type1.InternalGetFields(BindingFlags.NonPublic | (BindingFlags.Public | BindingFlags.Instance), false);
for (int num1 = 0; num1 < infoArray1.Length; num1++)//比较每个字段的值
{
object obj2 = ((RuntimeFieldInfo) infoArray1[num1]).InternalGetValue(obj1, false);
object obj3 = ((RuntimeFieldInfo) infoArray1[num1]).InternalGetValue(obj, false);
if (obj2 == null)
{
if (obj3 != null)
{
return false;
}
}
else if (!obj2.Equals(obj3))
{
return false;
}
}
return true;
}
可以这样实现:
struct MyValType
{
RefType refobj;
ValType valobj;
publci override Boolean Equals(Object obj)
{
if(!(obj is MyValType)) return false;
return this.Equals((MyValType)obj);
}
public Boolean Equals(MyValType obj)
{
if(!Object.Equals(this.refobj,obj.refobj)) return false;
if(!this.valobj.Equals(obj.valobj)) return false;
return true;
}
public static Boolean operator==(MyValType v1,MyValType v2)
{
return v1.Equals(v2);
}
public static Boolean operator!=(MyValType v1,MyValType v2)
{
return !(v1==v2);
}
}
{
RefType refobj;
ValType valobj;
publci override Boolean Equals(Object obj)
{
if(!(obj is MyValType)) return false;
return this.Equals((MyValType)obj);
}
public Boolean Equals(MyValType obj)
{
if(!Object.Equals(this.refobj,obj.refobj)) return false;
if(!this.valobj.Equals(obj.valobj)) return false;
return true;
}
public static Boolean operator==(MyValType v1,MyValType v2)
{
return v1.Equals(v2);
}
public static Boolean operator!=(MyValType v1,MyValType v2)
{
return !(v1==v2);
}
}