iComparable 接口工作

iComparable Interface Workings

我已经使用 iComparable 界面创建了一个客户 class。

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

    public int CompareTo(Customer obj)
    {
      if (this.Salary > obj.Salary)
          return 1;
        else if
            (this.Salary < obj.Salary)
            return -1;
        else
            return 0;
     }

}

在主程序中我创建了一个客户列表并添加了三个客户。

List<Customer> ListCust = new List<Customer>(); 
ListCust.Add(Cust1);
ListCust.Add(Cust2);
ListCust.Add(Cust3);

然后我对列表进行排序。

ListCust.Sort();

我的问题是这种列表排序方法如何提取客户 class 的 "CompareTo" 部分。最初,当我尝试在没有 iComparable 接口的情况下对其进行排序时,它给了我无效的操作错误。

下面的问题是为什么我不能在没有iComparable接口的情况下在客户class中创建一个"CompareTo"方法并使它起作用?

查看 Sort 方法的 MSDN 文档,它说

InvalidOperationException is thrown when comparer is null, and the default comparer Comparer.Default cannot find implementation of the IComparable generic interface or the IComparable interface for type T.

原来是这样设计的

.NET 无法 "just" 对您的 Customer 对象进行排序的原因是因为它无法猜测您希望以何种方式对它们进行排序:按薪水、按名字、按姓氏姓名,他们第一次下订单的时间等

但是,您可以通过三种不同的方式使其在不实施 IComparable 的情况下工作:

  • Pass a separate IComparer<Customer> 实现 - 这让您可以将比较逻辑移动到单独的 class,并根据情况应用不同的比较逻辑。
  • Pass a Comparison<Customer> delegate - 同上,但现在你不需要单独的 class;这使您可以在 lambda 中提供比较逻辑。
  • 改用 LINQ 的 OrderBy - 与上面类似,但提供了额外的功能(过滤、投影、分组等)

Sort方法检查类型参数是否实现了IComparable。如果是,该方法将列表中的每个项目转换为 IComparable。像这样的事情:(可能不是他们实际上做的,但你明白了。)

foreach (T item in this) {
    if (item is IComparable) {
        var castedItem = (IComparable)item;
        // do other things with castedItem
    } else {
        throw new InvalidOperationException("Sorting is not supported");
    }
}

因此,如果您不实施 IComparableitem is IComparable 的计算结果为 false,这就是抛出 InvalidOperationException 的原因。

所以,最终的原因是...

The source code doesn't check whether you have a CompareTo method or not. It just checks whether you have the interface implemented.