什么是Comparer <T>类?

Vin*_*cio 24 c#

Comparer<T>如果您指定的类型已经实现,该类的用途是什么IComparable

如果我指定Comparer.Default,并且Customer已经实现了IComparable,那么为什么我要使用Comparer类?

Mac*_*tka 22

因为你有时需要保持集合/有序队列按其他东西排序然后"自然"顺序或更多,然后存在一个自然顺序.

例如,如果您有平面线,您可能希望按以下方式对其进行排序:

  • 航班号
  • 目的地
  • 时间
  • 优先级(某些航班可能比其他航班延误更长)
  • ...

计算机中的任务可以安排:

  • 用户
  • 优先级(在调度程序中)
  • PID(正常比较)
  • ...

因此,即使在一个应用程序中,您可能需要按不同属性对对象进行排序.你不能通过int compareTo(Object)方法来做到这一点,因为它不能在上下文之间有所区别.但是,您可以添加上下文即实现CompareByPriority.


Jos*_*osh 18

我认为你的问题是为什么有一个基类似乎只有一个有用的方法,恰好是你直接实现接口时实现的方法.如果我理解正确的话,我猜你是正确的,除了基类通过单个重写方法为你提供泛型和非泛型实现之外,从直接Comparer<T>实现而不是IComparer<T>直接实现没有多少好处.

但如果你的问题是,为什么有两个IComparer<T>IComparable<T>,然后像其他人指出,Comparer<T>允许你定义不同的方式来进行比较.它是战略设计模式的实施.一个很好的例子是各种StringComparer属性,如StringComparer.Ordinal,StringComparer.OrdinalIgnoreCase等.这允许您在不同情况下对字符串进行不同的排序,而IComparable<T>界面根本无法预料.

但除了能够重新定义执行比较的方式之外,有时提供外部比较器是唯一可行的方法.例如,Windows窗体ListView类允许您为其排序逻辑指定IComparer.但ListViewItem不实现IComparable.因此,如果没有比较器策略知道如何操作,ListViewItem不可排序,因为它没有默认的IComparable实现.

因此,在一天结束时,它只是另一个可扩展性点,当您不是要排序的类型的作者(或者您需要多个排序策略)时,它允许您更灵活.


编辑:回应你的评论如下:"如果我有一个实现IComparer(我自己的类)的类,这将允许我排序任意数量的属性(自定义排序),为什么我会打扰使用Comparer.Default "

也许一个例子会有所帮助.假设您正在编写一个扩展方法,用于检查给定值是否在范围之间.

public static bool Between<T>(this T value, T minValue, T maxValue) {

    var comparer = Comparer<T>.Default;

    int c1 = comparer.Compare(value, minValue);
    int c2 = comparer.Compare(value, maxValue);

    return (c1 >= 0 && c2 <= 0);

}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我不知道关于类型T的任何信息.它可以实现IComparable或者它可以实现,IComparable<T>或者它可以不实现,并且将抛出异常.这也允许我轻松地为这个方法添加一个重载,让调用者在他们自己的比较器中传递.但Comparer在这里派上用场,因为它让我得到一个未知类型的默认比较器,它可能会也可能不会实现通用或非通用IComparable接口.


Kob*_*obi 9

该类型不需要实现IComparable,它可以是任何类型 - 没有约束T:

public abstract class Comparer<T> : IComparer, IComparer<T>
Run Code Online (Sandbox Code Playgroud)

Comparer您创建的新工具IComparer<T>和非泛型工具IComparer,可用于集合的比较和排序.

你是对的:如果你的类型,Customer工具IComparable,你不需要另一个比较,Comparer对你没用.大多数类在.NET Framework中,既可以接受IComparable<T>或者Comparer<T>,这样你就可以使用其中之一.

但是,你总是这样认为是错误的.可以Comparer为非Comparable类型创建一个.请注意,以下内容不是必需的:

public abstract class Comparer<T> : IComparer, IComparer<T>
                                    where T : IComparable, IComparable<T>
Run Code Online (Sandbox Code Playgroud)

假设你有一个简单的类,Person并且你想对列表进行排序Persons,最好把它写成一个Comparer:

public class Person
{
    string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ell 8

这里有一些微妙的要点:

  • 它不仅仅支持IComparable<T>- 它还支持旧版(非通用版)IComparable作为后备版.这意味着它不能表示为(例如)通用约束
  • 它支持Nullable<T>地方T相媲美,即使Nullable<T>显然是不 IComparableIComparable<T>
  • 它通过要求它们来防止泛型类型约束的爆炸- 例如,a List<T>可以提供一个Sort即使它并不坚持所有T都是可排序的; 你会惊讶于通用约束会以多快的速度累积
  • 它允许您将比较器传递给任何需要比较器的现有API,只要您拥有的是可以比较的类型 ; 大多数框架排序API(包括LINQ)都将提供比较器支持