[译]在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        [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 - 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/p/use-icomparable-icomparer.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:[译]在C#中使用IComparable和IComparer接口 - Python技术站

(0)
上一篇 2023年5月2日
下一篇 2023年5月3日

相关文章

  • 一篇文章带你轻松了解C# Lock关键字

    一篇文章带你轻松了解C# Lock关键字 Lock关键字是什么 Lock是C#编程中非常重要的一个关键字,主要用来进行多线程编程时的同步控制。在多线程程序中,不同的线程会同时对同一数据进行访问,如果没有同步控制,则有可能发生数据竞争的问题。使用Lock关键字可以保证在同一时间只有一个线程对共享资源进行访问。 Lock关键字的用法 Lock关键字用法非常简单,…

    C# 2023年5月15日
    00
  • C# TreeView读取数据库简单实例

    C# TreeView读取数据库简单实例 本文将介绍如何在C#的WinForms应用程序中,使用TreeView控件读取数据库数据,并在TreeView节点中展示出来。我们以展示行政区划(省市县)为例子。 确定数据库 我们首先要确定用于存放数据的数据库。在本例中,我们使用MySQL数据库。 创建数据库 我们需要先创建一个数据库,并在其中创建一个表结构,用于存…

    C# 2023年6月2日
    00
  • 电脑英文缩写大全

    为了让大家更好地了解“电脑英文缩写大全”的完整攻略,我将分为以下几个部分进行讲解: 1. 收集电脑英文缩写 首先,我们需要收集电脑英文缩写。可以从各种渠道去收集,比如: 在网上搜索相关的英文缩写资料; 浏览电脑文章、手册、技术文档等,注意其中使用的缩写; 参考行业内广泛流传的缩写资料,如IEEE 802.11、ISO 9660等。 收集到英文缩写之后,需要对…

    C# 2023年6月8日
    00
  • c# 如何实现不同进程之间的通信

    下面是关于“C#如何实现不同进程之间的通信”的完整攻略,包含两个示例。 1. 什么是进程间通信 进程间通信(IPC)是指在不同进程之间传递数据或信号的机制。在C#中,我们可以使用多种方式实现进程间通信,例如命名管道、共享内存、消息队列等。 2. 示例1:使用命名管道实现进程间通信 以下是一个示例,演示如何使用命名管道实现进程间通信: // 服务端 using…

    C# 2023年5月15日
    00
  • 如何使用C# Stopwatch 测量微秒级精确度

    使用C# Stopwatch测量微秒级精确度的完整攻略如下: 步骤 1:导入命名空间 首先,在代码文件的顶部,添加System.Diagnostics 命名空间,以便使用 Stopwatch 类: using System.Diagnostics; 步骤 2:初始化 Stopwatch 创建 Stopwatch 类示例,并调用 Start 方法(或 Rest…

    C# 2023年5月15日
    00
  • ASP.NET在VS2022中使用Dispose释放资源实例

    下面是关于ASP.NET在VS2022中使用Dispose释放资源实例的详细攻略。 什么是Dispose Dispose是IDisposable接口定义的方法,它是一种在释放一个对象的时候执行清理操作的方式。Dispose方法允许我们释放非托管资源、取消订阅事件和释放接口中的其他资源。 为什么需要使用Dispose 对于实现了IDisposable接口的对象…

    C# 2023年6月3日
    00
  • C# 基础入门–注释

    非常感谢你对C#基础学习的关注!注释是一种非常重要的编程元素,它能够加强代码的可读性、可维护性和可访问性。在本篇文章中,我将为您介绍如何在C#程序中使用注释,包括单行注释和多行注释。 单行注释 单行注释会在某一行的末尾添加标记符号“//”,表示该行后面的文字都是注释内容。例如,下面的代码演示了单行注释的使用: // 这是一个单行注释 int x = 5; /…

    C# 2023年6月7日
    00
  • C# winform打开Excel文档的方法总结(必看篇)

    以下是对“C# winform打开Excel文档的方法总结(必看篇)”的完整攻略: 简介 在C# WinForm开发中,我们经常需要读取并操作Excel文档。本文将介绍几种可行的Excel文档打开方法。 使用OleDb方式打开Excel文档 用Visual Studio创建一个新的WinForm程序项目,引用System.Data.OleDb应用程序集。 在…

    C# 2023年6月1日
    00
合作推广
合作推广
分享本页
返回顶部