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

时间:2015-11-18 16:51:25

标签: c# asp.net .net generics interface

我有一个班级:

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

我还有一个List:

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();

我理解为什么list.Sort不会在Customer上工作,因为Customer类有三个属性,并且它不知道如何对它进行排序。但是如果我在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进行排序?我甚至没有重写排序方法或任何东西。 我很困惑,因为我根本没有使用CompareTo方法。

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

4 个答案:

答案 0 :(得分:3)

当你实现IComparable<T>,创建一个public int CompareTo(T)方法时,你实际上在做的是告诉排序机制,它在别处定义,如何对两个实例进行排序通过比较一个实例与另一个实例来比较你

就像我说的那样,实际的排序机制在别处定义,例如: List<T>.Sort()。无论排序机制使用什么算法 - bubble sortquick sort等 - 都无关紧要,但它们都需要反复比较实例以产生排序结果。每次比较两个实例时,都会调用public int CompareTo(T)方法实现,因为您可以在其中定义如何将您的特定实现相互比较以生成排序结果。

答案 1 :(得分:1)

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

  

移动东西,使“较低”的物品出现在“较高”物品之前。

因此,所有种类都需要能够理解他们正在排序的对象的“更低”和“更高”。

这很容易用数字;例如3 < 4true,因为3低于4。即使仅使用数字,我们也必须为intlongdecimaldouble等编写不同的排序算法,因为我们无法使用泛型此处(<等运算符无法通过泛型提供),当然无法在<上使用object

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

我们也不能对我们不知道的类型进行任何排序,所以我们再次需要该机制来知道哪个是“较低”而哪个是“较高”。

IComaprable<T>IComparable就是这么做的。

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

排序通常用作:

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

  2. 如果我们未通过IComparer<T>,请使用Comparer<T>.Default

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

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

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

    2. 否则,如果类型实现IComparable(来自仿制药之前的旧界面),则使用它。

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

答案 2 :(得分:0)

CustomerList是具有泛型类型参数Customer的通用List。 Sort()方法的排序算法实现是通用列表提供的,并且通过查看Microsoft文档here,您可以看到实际上使用了三种算法,具体取决于列表的大小:

  
      
  • 如果分区大小少于16个元素,则使用插入   排序算法。
  •   
  • 如果分区数超过2 * LogN,则为N.   是输入数组的范围,它使用Heapsort算法。
  •   
  • 否则,它使用Quicksort算法。
  •   

算法都依赖于您对Customer类的IComparable实现,以了解如何订购客户对象。

答案 3 :(得分:0)

在List&lt; T&gt; .Sort()的代码中,它将是

  • 将每个对象投射到IComparable&lt; T&gt;,
  • 使用该接口调用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);
          }
      }
   }
}