[译]在C#中使用IComparable和IComparer接口

  • [译]在C#中使用IComparable和IComparer接口已关闭评论
  • 138 次浏览
  • A+
所属分类:.NET技术
摘要

原文:Use the IComparable and IComparer interfaces in Visual CSharp本文介绍了在Visual C#中如何使用IComparer和IComparable接口。

原文:Use the IComparable and IComparer interfaces in Visual CSharp

本文介绍了在Visual C#中如何使用IComparer和IComparable接口。

概要

本文同时讨论了IComparable和IComparer接口,原因有两点。这两个接口经常一起使用。虽然接口类似且名称相似,但它们却有不同的用途。

如果你有一个支持IComparer的类型数组(例如字符串或整数),你可以对它进行排序而不需要提供任何对IComparer的显式引用(译注:意思是把一个IComparer的实现类作为参数传递给排序方法)。在这种情况下,数组元素会被转换为IComparer的默认实现(Comparer.Default)。然而,如果你想为自定义对象提供排序或比较能力,你必须实现这两个接口中的一个或两个。

本文引用了Microsoft .NET Framework类库命名空间System.Collections。

IComparable 接口

IComparable 接口的作用是提供一种比较特定类型的两个对象的方法。如果你想为你的对象提供任何排序能力,那么这是必须的。可以将 IComparable 视为为你的对象提供默认的排序顺序。例如,如果你有一个对象类型的数组,然后你在该数组上调用 Sort 方法,则排序期间的对象比较是由 IComparable 提供的。当你实现 IComparable 接口时,必须实现 CompareTo 方法,如下所示:

// IComparable 的 CompareTo 方法,提供默认的排序。 int IComparable.CompareTo(object obj) {    Car c=(Car)obj;    return String.Compare(this.make,c.make); }

CompareTo 方法中如何进行比较取决于被比较值的数据类型。在本例中使用 String.Compare方法,因为被选择用于比较的属性是字符串。

IComparer 接口

IComparer 接口的作用是提供更多的比较机制。例如,你可能想要你的类的排序上使用多个字段或属性,在同一字段上提供升序和降序,或者两者兼而有之。(译注,这个时候就必须要使用IComparer 接口了。)

使用 IComparer 是一个两步过程。首先,声明一个实现 IComparer 的类,然后实现 Compare 方法:

private class SortYearAscendingHelper : IComparer {    int IComparer.Compare(object a, object b)    {       Car c1=(Car)a;       Car c2=(Car)b;       if (c1.year > c2.year)          return 1;       if (c1.year < c2.year)          return -1;       else          return 0;    } }

注意:

IComparer.Compare 方法需要三元比较。根据其中一个值是否大于、等于或小于另一个值,返回1、0或-1。可以通过切换此方法中的逻辑运算符来更改排序顺序(升序或降序)。

第二步是声明一个返回IComparer对象实例的方法:

public static IComparer SortYearAscending() {    return (IComparer) new SortYearAscendingHelper(); }

在本例中,该对象被用作第二个参数被传递给Array.Sort的接受IComparer实例的重载方法。IComparer的使用并不局限于数组。它被许多不同的集合和控件类接受为参数。

逐步讲解的示例:

以下示例演示了如何使用这些接口。为了演示IComparer和IComparable,我们创建了一个名为Car的类,该类拥有Make和Year两个属性。通过IComparable接口,为Make字段启用了升序排序;通过IComparer接口,为Make字段启用了降序排序。通过使用IComparer,为Year属性提供了升序和降序排序。

1. 在Visual Studio中创建一个新的Console Application项目,把它命名为ConsoleEnum。

2. 将Program.cs重命名为Host.cs,然后用以下代码替换原有代码。

 1 using System;  2   3 namespace ConsoleEnum  4 {  5     class host  6     {  7        [STAThread]  8        static void Main(string[] args)  9        { 10           // Create an array of Car objects. 11           Car[] arrayOfCars= new Car[6] 12           { 13              new Car("Ford",1992), 14              new Car("Fiat",1988), 15              new Car("Buick",1932), 16              new Car("Ford",1932), 17              new Car("Dodge",1999), 18              new Car("Honda",1977) 19           }; 20  21           // Write out a header for the output. 22           Console.WriteLine("Array - Unsortedn"); 23  24           foreach(Car c in arrayOfCars) 25              Console.WriteLine(c.Make + "tt" + c.Year); 26  27           // Demo IComparable by sorting array with "default" sort order. 28           Array.Sort(arrayOfCars); 29           Console.WriteLine("nArray - Sorted by Make (Ascending - IComparable)n"); 30  31           foreach(Car c in arrayOfCars) 32              Console.WriteLine(c.Make + "tt" + c.Year); 33  34           // Demo ascending sort of numeric value with IComparer. 35           Array.Sort(arrayOfCars,Car.SortYearAscending()); 36           Console.WriteLine("nArray - Sorted by Year (Ascending - IComparer)n"); 37  38           foreach(Car c in arrayOfCars) 39              Console.WriteLine(c.Make + "tt" + c.Year); 40  41           // Demo descending sort of string value with IComparer. 42           Array.Sort(arrayOfCars,Car.SortMakeDescending()); 43           Console.WriteLine("nArray - Sorted by Make (Descending - IComparer)n"); 44  45           foreach(Car c in arrayOfCars) 46              Console.WriteLine(c.Make + "tt" + c.Year); 47  48           // Demo descending sort of numeric value using IComparer. 49           Array.Sort(arrayOfCars,Car.SortYearDescending()); 50           Console.WriteLine("nArray - Sorted by Year (Descending - IComparer)n"); 51  52           foreach(Car c in arrayOfCars) 53              Console.WriteLine(c.Make + "tt" + c.Year); 54  55           Console.ReadLine(); 56        } 57    } 58 }

3. 在项目中新增一个类,命名为Car。

4. 用下面的代码替换Car.cs中的代码。

  1 using System;   2 using System.Collections;   3 namespace ConsoleEnum   4 {   5    public class Car : IComparable   6    {   7       // Beginning of nested classes.   8       // Nested class to do ascending sort on year property.   9       private class SortYearAscendingHelper: IComparer  10       {  11          int IComparer.Compare(object a, object b)  12          {  13             Car c1=(Car)a;  14             Car c2=(Car)b;  15   16             if (c1.year > c2.year)  17                return 1;  18   19             if (c1.year < c2.year)  20                return -1;  21   22             else  23                return 0;  24          }  25       }  26   27       // Nested class to do descending sort on year property.  28       private class SortYearDescendingHelper: IComparer  29       {  30          int IComparer.Compare(object a, object b)  31          {  32             Car c1=(Car)a;  33             Car c2=(Car)b;  34   35             if (c1.year < c2.year)  36                return 1;  37   38             if (c1.year > c2.year)  39                return -1;  40   41             else  42                return 0;  43          }  44       }  45   46       // Nested class to do descending sort on make property.  47       private class SortMakeDescendingHelper: IComparer  48       {  49          int IComparer.Compare(object a, object b)  50          {  51             Car c1=(Car)a;  52             Car c2=(Car)b;  53              return String.Compare(c2.make,c1.make);  54          }  55       }  56       // End of nested classes.  57       private int year;  58       private string make;  59   60       public Car(string Make,int Year)  61       {  62          make=Make;  63          year=Year;  64       }  65   66       public int Year  67       {  68          get  {return year;}  69          set {year=value;}  70       }  71   72       public string Make  73       {  74          get {return make;}  75          set {make=value;}  76       }  77       // Implement IComparable CompareTo to provide default sort order.  78       int IComparable.CompareTo(object obj)  79       {  80          Car c=(Car)obj;  81          return String.Compare(this.make,c.make);  82       }  83       // Method to return IComparer object for sort helper.  84       public static IComparer SortYearAscending()  85       {  86          return (IComparer) new SortYearAscendingHelper();  87       }  88       // Method to return IComparer object for sort helper.  89       public static IComparer SortYearDescending()  90       {  91          return (IComparer) new SortYearDescendingHelper();  92       }  93       // Method to return IComparer object for sort helper.  94       public static IComparer SortMakeDescending()  95       {  96         return (IComparer) new SortMakeDescendingHelper();  97       }  98   99    } 100 }

5. 运行项目。Console窗口显示如下:

Array - Unsorted  Ford 1992 Fiat 1988 Buick 1932 Ford 1932 Dodge 1999 Honda 1977  Array - Sorted by Make (Ascending - IComparable)  Buick 1932 Dodge 1999 Fiat 1988 Ford 1932 Ford 1992 Honda 1977  Array - Sorted by Year (Ascending - IComparer)  Ford 1932 Buick 1932 Honda 1977 Fiat 1988 Ford 1992 Dodge 1999  Array - Sorted by Make (Descending - IComparer)  Honda 1977 Ford 1932 Ford 1992 Fiat 1988 Dodge 1999 Buick 1932  Array - Sorted by Year (Descending - IComparer)  Dodge 1999 Ford 1992 Fiat 1988 Honda 1977 Buick 1932 Ford 1932