.NET框架中的IComparable、IComparable、IComparer、IEqualityComparer

  • Post author:
  • Post category:其他


定义如下:



public


interface


IComparable

{




int


CompareTo(

object

obj);

}



public


interface


IComparer<T>

{




int


Compare(T x, T y);

}



public


interface


IComparable<T>

{




int


CompareTo(T other);

}



public




interface


IEqualityComparer<T>

{




bool


Equals(T x, T y);



int


GetHashCode(T obj);

}

对于特定类型实现IComparer<T>接口,这样当你在实现排序算法时,即可调用IComparer<T>.Compare(T x, T y)进行对实例x,y的比较,方法返回值小于0,表明x小于y,若返回值等于0,表明x等于y,若返回值大于0,表明x大于y。对于IComparable<T>接口,当某类型实现该接口时,就可以再该类型实例上调用CompareTo(T other)方法,方法返回值小于0,表明实例小于other参数,若返回值等于0,表明实例等于other参数,若返回值大于0,表明实例大于other参数。对于IEqualityComparer<T>接口,可以根据对该接口的实现类,调用Equals(T x, T y)方法,返回true表明x和y相等。

现在准备一个雇员类,内含三个成员(年龄、姓名、所在部门),根据年龄大小来判断大小,年龄大的雇员大于年龄小的雇员。代码如下:

public class Employee : IComparable<Employee>
{
        public int Age
        {
            get;
            set;
        }
        public string Name
        {
            get;
            set;
        }
        public string Department
        {
            get;
            set;
        }
        public Employee(int age,string name,string department)
        {
            this.Age = age;
            this.Name = name;
            this.Department = department;
        }

        #region IComparable<Employee> Members

        public int CompareTo(Employee other)
        {
            if (this.Age < other.Age) return -1;
            if (this.Age == other.Age) return 0;
            return 1;
        }

        #endregion
}

static void Main(string[] args)
{
            Employee anders = new Employee(35, "Anders Wang", "Developer Division");
            Employee jeffrey = new Employee(28, "Jeffrey Chen", "Developer Division");
            Console.WriteLine(anders.CompareTo(jeffrey)); // output 1
            Console.ReadKey();
}

从Employee的CompareTo看出,由于anders的Age>jeffrey的Age,所以anders.CompareTo(jeffrey)返回1,表明实例anders大于实例jeffrey。

也可以通过实现接口IComparer<T>,实现比较的功能。代码如下:

class EmployeeComparer:IComparer<Employee>
{

        #region IComparer<Employee> Members

        public int Compare(Employee x, Employee y)
        {
            if (x.Age < y.Age) return -1;
            if (x.Age == y.Age) return 0;
            return 1;
        }

        #endregion
    }
}
static void Main(string[] args)
{
            Employee anders = new Employee(35, "Anders Wang", "Developer Division");
            Employee jeffrey = new Employee(28, "Jeffrey Chen", "Developer Division");
            Console.WriteLine(new EmployeeComparer().Compare(anders, jeffrey));//output 1
            Console.ReadKey();
}

以上代码也同样实现了比较功能。

要判断两个对象是否相等?我们可以通过实现IEqualityComparer<T>接口或者通过调用基类object的Equals方法。但是在大部分情况下,调用基类object的Equals方法需要进行强制转换,含有类型不安全的问题。下面我们通过EmployeeEqualityComparer来实现IEqualityComparer<T>。代码如下:

public class EmployeeEqualityComparer:IEqualityComparer<Employee>
{
        #region IEqualityComparer<Employee> Members

        public bool Equals(Employee x, Employee y)
        {
            if (x.Age == y.Age && x.Name == y.Name && x.Department == y.Department)
            {
                return true;
            }
            return false;
        }

        public int GetHashCode(Employee obj)
        {
            //由于是根据Age,Name,Department来进行判等的,
            //所以哈希值的求取过程也要进行一定的修改,
            //确保相等对象的哈希值也是相等的。
            return obj.GetHashCode();
        }

        #endregion
}


static void Main(string[] args)
{
            Employee anders = new Employee(35, "Anders Wang", "Developer Division");
            Employee jeffrey = new Employee(28, "Jeffrey Chen", "Developer Division");
            Employee steve = new Employee(35, "Anders Wang", "Developer Division");
            Console.WriteLine(new EmployeeEqualityComparer().Equals(anders, jeffrey)); //output false
            Console.WriteLine(new EmployeeEqualityComparer().Equals(anders, steve)); //output true
            Console.ReadKey();
}

以上代码通过实现IEqualityComparer<T>接口说明了如何判断两个对象相等。

.NET框架提供了IComparable、IComparable<T>、IComparer<T>、IEqualityComparer<T>,这几个接口对于实现排序算法有着直接的作用,在泛型的帮助下,可以编写出通用的排序算法,只需要你根据特定的类型实现以上几个接口中的方法。正是因为接口,使得大家都有了规约,进而使得通用的排序算法实现变得可能。另外在处理和集合相关的类型时,比如字典,哈希表等数据结构时,当你因为具体的语义覆盖了键类型的Equals方法后,务必必也要覆盖GetHashCode方法。