先看一下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;
}

在设计类型的时候可以分3种情况:
1、我们当前所设计的引用类的基类型如果没有重写Object的Equals方法而是直接继承得来,那么实现Equals方法可以这样:
class MyRefType : BaseType
{
 RefType refobj;
 ValType valobj;
 
public override Boolean Equals(Object obj)
 
{
    
if(obj == nullreturn 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 == nullreturn 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;
}



可以这样实现:
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);
    }

}


posted on 2004-12-02 01:37  烂瓶子  阅读(968)  评论(3编辑  收藏  举报