构建可比较的对象(IComparable)

IComparable接口  System.IComparable接口指定了一种允许一个对象可基于某些特定键值进行排序的行为。
namespace System
{
    [ComVisible(true)]
    public interface IComparable
    {
        int CompareTo(object obj);
    }
}
CompareTo()方法背后的逻辑是,根据某个特定数据字段比较传入的对象与当前实例。CompareTo()方法的返回值被用来判断这个类型小于、大于或是等于它所比较的对象。
  • 任何小于0的数字:这个实例在指定对象之前
  • 0:这个实例等于指定对象
  • 任何大于0的数字:这个实例在指定对象之后
  •  构建可比较对象  System.Array类定义了一个名为 Sort()的静态方法。在内置类型(int、short、string等)上调用这个方法的时候,可以以数字/字母顺序对数组中的项排序,因为这些内置数据类型实现了IComparable。构建可排序的Car类型
    namespace ComparableCar
    {
        class Car : IComparable
        {
            public int CurrentSpeed { get; set; }
            public string PetName { get; set; }
            public int CarID { get; set; }
    public Car() { } public Car( string name, int currSp, int id ) { CurrentSpeed = currSp; PetName = name; CarID = id; }

    int IComparable.CompareTo(object obj) { Car temp = obj as Car; if (temp != null) { if (this.CarID > temp.CarID) return 1; if (this.CarID < temp.CarID) return -1; else return 0; } else throw new ArgumentException("Parameter is not a Car!"); } } }
      由于C#int数据类型(只是CLR System.Int32的简写形式)实现了IComparable,我们就可以按如下所示的方法实现ICompareTo()方法:
            int IComparable.CompareTo( object obj )
            {
                Car temp = obj as Car;
                if (temp != null)
                    return this.CarID.CompareTo(temp.CarID);
                else
                    throw new ArgumentException("Parameter is not a Car!");
            }
      Car类型已经知道如何将它自己和类似对象进行对比:
    namespace ComparableCar
    {
        class Program
        {
            static void Main( string[] args )
            {
                Console.WriteLine("***** Fun with Object Sorting *****n");
    Car[] myAutos = new Car[5]; myAutos[0] = new Car("Rusty", 80, 1); myAutos[1] = new Car("Mary", 40, 234); myAutos[2] = new Car("Viper", 40, 34); myAutos[3] = new Car("Mel", 40, 4); myAutos[4] = new Car("Chucky", 40, 5); Console.WriteLine("Here is the unordered set of cars:"); foreach (Car c in myAutos) Console.WriteLine("{0} {1}", c.CarID, c.PetName); Array.Sort(myAutos); Console.WriteLine(); Console.WriteLine("Here is the ordered set of cars:"); foreach (Car c in myAutos) Console.WriteLine("{0} {1}", c.CarID, c.PetName); Console.ReadLine(); } } }
     指定多个排序顺序IComparer  如果要构建一个既可通过ID排序又可通过昵称排序的Car类型,就需要与另一个标准接口IComparer打交道。
    namespace System.Collections
    {
        [ComVisible(true)]
        public interface IComparer
        {
            int Compare(object x, object y);
        }
    }
       与IComparable接口不同,IComparer接口不是在要排序的类型(即Car)中,而是在许多辅助类中实现的,其中每个排序各有一个依据(如昵称、ID号等)。
    namespace ComparableCar
    {
        //  这个辅助类用来通过昵称排序Car类型的数组
        public class PetNameComparer : IComparer
        {
            // 测试每个对象的昵称
            int IComparer.Compare( object o1, object o2 )
            {
                Car t1 = o1 as Car;
                Car t2 = o2 as Car;
                if (t1 != null && t2 != null)
                    return String.Compare(t1.PetName, t2.PetName);
                else
                    throw new ArgumentException("Parameter is not a Car!");
            }
        }
    }
       System.Array有许多重载的Sort()方法,其中有一个用来在对象上实现IComparer接口。
    namespace ComparableCar
    {
        class Program
        {
            static void Main( string[] args )
            {
                ...// 按照昵称进行排序
                Array.Sort(myAutos, new PetNameComparer());
    
                Console.WriteLine("Ordering by pet name:");
                foreach (Car c in myAutos)
                    Console.WriteLine("{0} {1}", c.CarID, c.PetName);
                ...
            }
        }
    }
     自定义属性、自定义排序类型   值得指出的是,在通过特定数据字段排序Car类型的时候,可以使用自定义的静态属性辅助对象用户。假定Car类型添加了一个静态只读属性SortByPetName,它返回一个实现了IComparer接口的对象的实例(在本例中为PetNameComparer):
    namespace ComparableCar
    {
    // 现在可以使用一个自定义静态属性来返回正确的IComparer接口
    class Car : IComparable {
    ... // 返回SortByPetName比较的属性 public static IComparer SortByPetName { get { return (IComparer)new PetNameComparer(); } }
         ...
    } }
       现在可以使用强关联属性按照昵称排序,而不是只能使用独立的PetNameComparer类型:
    // 简洁明了的按照昵称排序
    Array.Sort(myAutos, Car.SortByPetName);

    相关内容推荐