结论

    对于值类型,总是需要重写Equals和operator
    对于引用类型,默认只是引用比较,只有在需要内容比较的时候才需要重写Equals,注意不需要重写operator
    重写遵照标准模式 

C#中四个相等判断

    public static bool ReferenceEquals(object left, object right);// 没有必要定义相同的方法
    public static bool Equals(object left, object right);// 没有必要定义相同的方法
    public virtual bool Equals(object right);// 重写
    public static bool operator ==(MyClass left, MyClass right); // 注意这里的MyClass是值类型
     

何时需要重写Equals和operator

    C#类型中的类有两种,分别是值类型和引用类型
    比较也有两种,分别是引用比较和内容比较,其中内容比较包括类型和值都必须相等

    对于值类型,总是需要重写Equals和operator,因为以前的实现应用了过多的反射,直接影响性能
    对于引用类型,默认只是引用比较,只有在需要内容比较的时候才需要重写Equals,注意不需要重写operator
      

 


重写的标准模式   

    不管是重写Equals还是operator,都可以套这个模式
    但当处理有继承关系的类的时候需要遵循这么一条经验法则:
    重写子类中的Equals()方法时,如果基类的Equals()方法不是由System.Ojbect或System.ValueType提供的话,应该调用基类的Equals()方法

     以下的这个标准模式按照child继承parent来写
    

using System;
using System.Collections.Generic;
using System.Text;

namespace EffectiveCode
{
public class Parent
    {
        public override bool Equals(object right)
        {
            if (right == null)
                return false;

            // 高效比较对象标识,即引用比较
            if (object.ReferenceEquals(this, right))
                return true;

            // 精确比较类型,这个跟is不同,is更偏向兼容,子类和父类也算相同,而GetType更为严格,子就是子,父就是父。
            if (this.GetType() != right.GetType())
                return false;

            // 内容比较
            return CompareParentMembers(this, right as Parent);
        }

        // 内容比较
        private bool CompareParentMembers(Parent parent, Parent parent_2)
        {
            return true;
        }
    }

    public class Child : Parent
    {
        public override bool Equals(object right)
        {
            if (right == null)
                return false;

            // 高效比较对象标识,即引用比较
            if (object.ReferenceEquals(this, right))
                return true;

            // 遵守经验法则,因为Parent这个基类的Equals()方法不是由System.Ojbect或System.ValueType提供,如果是就不能直接这么写,就要改成
            //if (this.GetType() != right.GetType())
            //    return false;
            if (base.Equals(right) == false)
                return false;

            // 内容比较
            return CompareParentMembers(this, right as Child);
        }

        // 内容比较
        private bool CompareParentMembers(Child parent, Child parent_2)
        {
            return true;
        }
    }
}

重写注意事项?

    1、重写时必须重写GetHashCode()
    主要原因是默认从Object继承来的hashCode是基于对象的ID实现的. 
    如果你重载了equals,比如说是基于对象的内容实现的,而保留hashCode的实现不变,那么很可能某两个对象明明是“相等”,而hashCode却不一样. 
    这样,当你用其中的一个作为键保存到hashMap、hasoTable或hashSet中,再以“相等的”找另一个作为键值去查找他们的时候,则根本找不到. 
    ——而这是反直觉的,因为“我要找的就是那个相等的对象,他明明在,我却找不到”.
    2、在比较值类型时,应当避免装箱操作

posted on 2012-05-09 21:52  Evildoer  阅读(451)  评论(0)    收藏  举报