[译]在C#中使用IComparable和IComparer接口
Posted 我们需要什么
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[译]在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,然后用以下代码替换原有代码。
using System; namespace ConsoleEnum class host [STAThread] static void Main(string[] args) // Create an array of Car objects. Car[] arrayOfCars= new Car[6] new Car("Ford",1992), new Car("Fiat",1988), new Car("Buick",1932), new Car("Ford",1932), new Car("Dodge",1999), new Car("Honda",1977) ; // Write out a header for the output. Console.WriteLine("Array - Unsorted\\n"); foreach(Car c in arrayOfCars) Console.WriteLine(c.Make + "\\t\\t" + c.Year); // Demo IComparable by sorting array with "default" sort order. Array.Sort(arrayOfCars); Console.WriteLine("\\nArray - Sorted by Make (Ascending - IComparable)\\n"); foreach(Car c in arrayOfCars) Console.WriteLine(c.Make + "\\t\\t" + c.Year); // Demo ascending sort of numeric value with IComparer. Array.Sort(arrayOfCars,Car.SortYearAscending()); Console.WriteLine("\\nArray - Sorted by Year (Ascending - IComparer)\\n"); foreach(Car c in arrayOfCars) Console.WriteLine(c.Make + "\\t\\t" + c.Year); // Demo descending sort of string value with IComparer. Array.Sort(arrayOfCars,Car.SortMakeDescending()); Console.WriteLine("\\nArray - Sorted by Make (Descending - IComparer)\\n"); foreach(Car c in arrayOfCars) Console.WriteLine(c.Make + "\\t\\t" + c.Year); // Demo descending sort of numeric value using IComparer. Array.Sort(arrayOfCars,Car.SortYearDescending()); Console.WriteLine("\\nArray - Sorted by Year (Descending - IComparer)\\n"); foreach(Car c in arrayOfCars) Console.WriteLine(c.Make + "\\t\\t" + c.Year); Console.ReadLine();
3. 在项目中新增一个类,命名为Car。
4. 用下面的代码替换Car.cs中的代码。
using System; using System.Collections; namespace ConsoleEnum public class Car : IComparable // Beginning of nested classes. // Nested class to do ascending sort on year property. 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; // Nested class to do descending sort on year property. private class SortYearDescendingHelper: 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; // Nested class to do descending sort on make property. private class SortMakeDescendingHelper: IComparer int IComparer.Compare(object a, object b) Car c1=(Car)a; Car c2=(Car)b; return String.Compare(c2.make,c1.make); // End of nested classes. private int year; private string make; public Car(string Make,int Year) make=Make; year=Year; public int Year get return year; set year=value; public string Make get return make; set make=value; // Implement IComparable CompareTo to provide default sort order. int IComparable.CompareTo(object obj) Car c=(Car)obj; return String.Compare(this.make,c.make); // Method to return IComparer object for sort helper. public static IComparer SortYearAscending() return (IComparer) new SortYearAscendingHelper(); // Method to return IComparer object for sort helper. public static IComparer SortYearDescending() return (IComparer) new SortYearDescendingHelper(); // Method to return IComparer object for sort helper. public static IComparer SortMakeDescending() return (IComparer) new SortMakeDescendingHelper();
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
C#中的IComparable和IComparer接口
C#中,自定义类型,支持比较和排序,需要实现IComparable接口。IComparable接口存在一个名为CompareTo()的方法,接收类型为object的参数表示被比较对象,返回整型值:1表示当前对象大于被比较对象,0表示两者相等,-1表示当前对象小于被比较对象。
public int CompareTo(object o)
若想以更加灵活的方式对自定义类进行比较,可以声明一个继承自IComparer接口的比较器,实现接口方法Comprae(),接收2个object类型参数作为比较对象,返回整型值:1表示前者大于后者,0表示两者相等,-1表示前者小于后者。
public int Compare(object x, object y)
IComparable是“可比较的”意思,自定义类实现该接口,就具有可比较的功能;IComparer是“比较器”的意思,实现该接口的类就是一个比较器,可以将比较器“注入”类中,使类具有比较和排序的功能。
具体事例可以参考本人以前整理的两篇博文。
IComparable接口示例代码
IComparer接口示例代码
以上是关于[译]在C#中使用IComparable和IComparer接口的主要内容,如果未能解决你的问题,请参考以下文章