自定义类型数组排序的两种实现方式
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版)