CompareTo 方法在实现 IComparable 时如何工作

本文关键字:何工作 工作 方法 实现 IComparable CompareTo | 更新日期: 2023-09-27 18:22:30

我有一个类:

 public class Customer :IComparable<Customer>
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public int Salary { get; set; }
        }

我还有一个清单:

Customer cust = new Customer() { Id=10,Name="Jack",Salary= 15000};
            Customer cust1 = new Customer() { Id = 10, Name = "Abby", Salary = 5000 };
            Customer cust2 = new Customer() { Id = 10, Name = "Zed", Salary = 152000 };
            List<Customer> CustomerList = new List<Customer>();
            list.Add(cust);
            list.Add(cust1);
            list.Add(cust2);
            CustomerList.Sort();

我明白为什么列出。排序不适用于客户,因为客户类有三个属性,它不知道如何排序。但是,如果我在类中实现接口IComparable Customer我就可以以任何我想要的方式对客户列表进行排序。

public class Customer :IComparable<Customer>
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public int Salary { get; set; }
            public int CompareTo(Customer other)
            {
                return this.Salary.CompareTo(other.Salary);
            }            
        }

现在我的问题是..实现 CompareTo 方法如何让我对CustomerList进行排序?我什至没有覆盖排序方法或任何东西。我很困惑,因为我根本没有使用过比较方法。

我读了 https://stackoverflow.com/a/4188041/2064292 但它没有回答我的问题。

CompareTo 方法在实现 IComparable 时如何工作

当你实现IComparable<T> 时,创建一个public int CompareTo(T)方法,你本质上要做的是告诉排序机制(在其他地方定义(如何通过将一个实例与另一个实例进行比较来对类的两个实例进行排序。

就像我说的,实际的排序机制在其他地方定义,例如 List<T>.Sort() . 无论排序机制使用什么算法 - 冒泡排序,快速排序等 - 都是无关紧要的,但它们都需要一遍又一遍地比较实例以产生排序结果。 每次比较两个实例时,都会调用public int CompareTo(T)方法实现,因为这是您定义如何将特定实现相互比较以产生排序结果的地方。

虽然有很多不同的排序算法,但它们都归结为同一件事:

移动内容,使"较低"项目位于"较高"项目之前。

因此,各种类型都需要能够理解它们正在排序的对象"较低"和"较高"。

对于数字来说,这很容易;例如 3 < 4 true,因为3低于4。即使只是数字,我们也必须为intlongdecimaldouble等编写不同的排序算法,因为我们不能在这里使用泛型(像<这样的运算符无法通过泛型获得(,当然也不能在object上使用<

因此,我们需要定义一些机制,通过该机制,.NET 可以为各种数字以及字符串等提供默认的"较低"和"较高"逻辑。

我们

也无法对我们不知道的类型进行任何排序,因此我们再次需要这种机制来知道哪个是"低"的,哪个是"高"。

IComaprable<T>IComparable这样做。

我们还有IComparer<T>IComparer,允许我们定义自定义订单(例如,对区分大小写和非区分大小写的搜索具有不同的逻辑(,或者允许某人在未实现IComparer的类型上提供订单。

排序通常工作为:

  1. 如果我们被传递了一个IComparer<T>对象,使用它来决定哪个更低或更高。

  2. 如果我们没有通过IComparer<T>则使用 Comparer<T>.Default .

使用 Comparer<T>.Default 意味着当我们没有IComparer<T>时,我们不需要单独的排序,我们只使用默认值。

现在,Comparer<T>.Default的工作方式如下:

  1. 如果类型实现了IComparable<T>则调用它。

  2. 否则,如果类型实现IComparable(泛型之前的旧接口(,则使用它。

  3. 否则会引发异常,因为无法知道如何订购任何东西。

CustomerList 是具有泛型类型参数 Customer 的泛型列表。Sort(( 方法的排序算法实现是泛型列表提供的算法实现,通过查看此处的Microsoft文档,您可以看到实际上根据列表的大小使用了三种算法:

  • 如果分区大小少于 16 个元素,则使用插入 排序算法。
  • 如果分区数超过 2 * LogN,其中 N 是输入数组的范围,它使用堆排序算法。
  • 否则,它将使用快速排序算法。

这些算法都依赖于 IComparable 的实现,以便 Customer 类知道如何对客户对象进行排序。

在List的代码中。排序((,它将是

  • 将每个对象转换为 IComparable
  • 使用该接口调用 CompareTo((,
  • 该调用的结果决定了排序顺序。

例如:

// Sorts a list using IComparable<T>
public static void Sort(this List<T> list)
{
   // Worst sorting algorithm ever
   for (int i = 0; i < list.Count; ++i)
   {
      for (int j = 0; j < list.Count; ++j)
      {
          // Assumes that type T implements IComparable<T>
          IComparable<T> first  = (list[i] as IComparable<T>);
          IComparable<T> second = (list[j] as IComparable<T>);
          if (first.CompareTo(second) > 0)
          {
              // wrong order
              Swap(list, i, j);
          }
      }
   }
}