饶紫聪 发表于 2023-4-26 14:40:17

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

原文: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      
8      static void Main(string[] args)
9      {
10         // Create an array of Car objects.
11         Car[] arrayOfCars= new Car
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 - Unsorted\n");
23
24         foreach(Car c in arrayOfCars)
25            Console.WriteLine(c.Make + "\t\t" + 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 + "\t\t" + 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 + "\t\t" + 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 + "\t\t" + 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 + "\t\t" + 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 

来源:https://www.cnblogs.com/wenhx/archive/2023/04/26/use-icomparable-icomparer.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: [译]在C#中使用IComparable和IComparer接口