自定义类型数组排序的两种实现方式

Array类是C#中所有自定义类型数组的抽象类。这种自定义类型数组可以像String类型一样进行排序。这种排序的方法C#在基础类库中已经实现了,并且向外提供了可用的接口。只要按照C#中提供的方法就可以方便地实现自定义数组的排序。

方式一:

自定义类Person如下,想实现先按FirstName排序,再按LastName排序。如果Person类的代码可以修改的话,只要让Person类继承IComparable接口或IComparable<T>接口。该接口只提供了一个方法CompareTo(T),用这个方法返回一个Int值用以说明比较对象的大小。方法内的代码就是自定义的排序规则。

class Person
    {
        // 属性创建快捷键 Ctr+R,E
        private string firstName;
        private string lastName;

        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }

        public string LastName
        {
            get { return lastName; }
            set { lastName = value; }
        }
       
        public override string ToString()
        {
            return firstName + " " + lastName;
        }
    }

本例的自定义规则是先按FirstName排序,再按LastName排序,代码如下:

class Person : IComparable<Person>
    {
        private string firstName;
        private string lastName;

        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }

        public string LastName
        {
            get { return lastName; }
            set { lastName = value; }
        }
        // IComparable<>接口实现
        public int CompareTo(Person other)
        {
            if (other == null) throw new ArgumentNullException("other");

            int result = String.Compare(firstName, other.firstName);
            if (result == 0)
            {
                result = String.Compare(lastName, other.lastName);
            }
            return result;
        }

        public override string ToString()
        {
            return firstName + " " + lastName;
        }
    }

方式二:

有时已定义的类的代码允许修改或根本没有源代码只有DLL的时候,另一种方法就可以用了。这种方法是创建另一个自定义的继承IComparer接口或IComparer<T>接口的类,用来辅助自定义类的排序。该接口只提供了方法Compare(x,y)。(类似CompareTo(T)) 用这个方法返回一个Int值用以说明比较对象的大小。方法内的代码就是自定义的排序规则。。在辅助类PersonCompare中排序的规则定义了两条,一是先按LastName排序,再按FirstName排序,二是先按FirstName排序,再按LastName排序。并用了一个Enum枚举类来区分这两种排序。代码如下:

enum PersonCompareType
    {
        FirstName,
        LastName
    }

    class PersonCompare : IComparer<Person>
    {
        private PersonCompareType compareType;

        public PersonCompare(PersonCompareType compareType)
        {
            this.compareType = compareType;
        }
        // IComparer<>接口实现
        public int Compare(Person x, Person y)
        {
            if (x == null) throw new ArgumentNullException("X");
            if (y == null) throw new ArgumentNullException("Y");
            int result = 0;
            switch (compareType)
            {
                // 先按LastName排序
                case PersonCompareType.LastName:
                    {
                        result = x.LastName.CompareTo(y.LastName);
                        if (result == 0)
                        {
                            result = x.FirstName.CompareTo(y.FirstName);
                        }
                    }
                    break;
                // 先按FirstName排序
                case PersonCompareType.FirstName:
                    {
                        result = x.FirstName.CompareTo(y.FirstName);
                        if (result == 0)
                        {
                            result = x.LastName.CompareTo(y.LastName);
                        }
                    }
                    break;
                default:
                    {
                        throw new ArgumentException("unexpected compare type");
                    }
            }
            return result;
        }
    }

两种方式的使用如下:

 static void Main(string[] args)
        {
            Person[] ps = { new Person { FirstName = "A", LastName = "C" },
                           new Person { FirstName = "C", LastName = "D" },
                           new Person { FirstName = "B", LastName = "A" }
                         };
            Console.WriteLine("FirstName");
            // 方式一 (先按FirstName排序)
            Array.Sort(ps);
            foreach (Person p in ps)
            {
                Console.WriteLine("{0}", p.ToString());
            }
            Console.WriteLine("LastName");
            // 方式二 (先按LastName排序)
            Array.Sort(ps, new PersonCompare(PersonCompareType.LastName));
            foreach (Person p in ps)
            {
                Console.WriteLine("{0}", p.ToString());
            }
            Console.WriteLine("FirstName");
            // 方式二 (先按FirstName排序)
            Array.Sort(ps, new PersonCompare(PersonCompareType.FirstName));
            foreach (Person p in ps)
            {
                Console.WriteLine("{0}", p.ToString());
            }
            Console.ReadKey();
        }

使用Array类的两个Sort方法分别与上述两种方式相结合实现排序。方式一与只有自定义数组本身的Sort方法联合使用。方式二与有自定义数组和IComparer类型两个参数的Sort方法一起使用。其实自己只需要实现排序规则说明的方法。而具体用什么方法排序是由C#基础类库实现的(当然我们也可以根据需求自己实现)。C#基础类库中用的排序方法是QuickSort算法,有机会看看源代码。

结果如下:

参考:C# 高级编程(第7版)

 

posted @ 2014-01-16 21:34  niaomingjian  阅读(2769)  评论(0编辑  收藏  举报