何时使用IComparable <T>VS。IComparer <T>


Answers:


96

那么,他们是不是相当同样的事情IComparer<T>在一个类型,能够在比较两个不同对象的实现IComparable<T>是在那些能够将自己与其他同类型的实例比较类型来实现。

IComparable<T>当我需要了解另一个实例与实例之间的关系时,我会经常使用它thisIComparer<T>作为IComparer<T>比较之外的标准,可用于对集合进行排序。


9
IComparer <T>还允许您为所需的每种类型的分类提供一个类。例; PersonLastFirstNameComparer,PersonFirstLastNameComparer或PersonAgeComparer。
埃里克·施耐德

您是否有一种简单的方式来记住它们?我倾向于每次都要查一下。
amadib 2012年

59
@amadib想IComparable我可比。这意味着我可以与其他事物进行比较。和阅读IComparer作为我是一个比较器,我简单地比较,这意味着我比一些事情。
nawfal 2012年

@newfal您应该已将此作为答案。我认为这是最好的解释。
Gene S

42

使用IComparable<T>时,班里有一个内在的比较。

使用IComparer<T>当你想比类内在比较其他的比较方法,如果它有一个。


28

它取决于实体。例如,对于诸如“ Student”之类的类,遵循基于Name的IComparable是有意义的。

class Student : IComparable 
{
    public string Name { get; set; }
    public int MathScore { get; set; }
    public int EnglishScore { get; set; }

    public int TotalScore 
    {
        get
        {
            return this.MathScore + this.EnglishScore; 
        }
    }

    public int CompareTo(object obj)
    {
        return CompareTo(obj as Student);  
    }

    public int CompareTo(Student other)
    {
        if (other == null)
        {
            return 1;
        }
        return this.Name.CompareTo(other.Name);  
    }
}

但是,如果老师“ A”想要比较基于MathScore的学生,而老师“ B”想要比较基于EnglishScore的学生。最好单独实现IComparer。(更像是一种策略模式)

class CompareByMathScore : IComparer<Student>
{
    public int Compare(Student x, Student y)
    {
        if (x.MathScore > y.MathScore)
          return 1;
        if (x.MathScore < y.MathScore)
          return -1;
        else
          return 0;
    }
}

将Compare方法设为静态以便于使用。

9

这完全取决于您的类型是否可变。你应该非可变类型实现IComparable。请注意,如果实现IComparable,则必须重写Equals以及==,!=,<和>运算符(请参阅代码分析警告CA1036)。

从此博客文章引用Dave G :

但是正确的答案是,如果您的对象是可变的,则实现IComparer而不是IComparable,并在必要时将IComparer的实例传递给排序函数。

由于IComparer只是该时间点用于排序的一次性对象,因此您的对象可以具有所需的任何可变语义。此外,它甚至不需要甚至不建议使用Equals,GetHashCode或==-您可以随意定义它。

最后,您可以为您的类型定义多个IComparer,以对不同的字段或不同的规则进行排序。这比坚持一个定义要灵活得多。

简而言之: 将IComparable用于值类型,将IComparer用于引用类型。


6

通过故事简单说明

高中篮球。对于团队来说,这是一个校园选择。我想招募团队中最高/最高/最快的人。我该怎么办?

IComparer界面 -比较两个人分开的人

  • 这使我可以比较排队的任何两个人……基本上就是这样。弗雷德(Vred)与约翰(John)..........我将它们放入实现该接口的具体类中。Compare(Fred, John)它吐出谁更好。

IComparable呢?-与别人比较自己

您最近去过FB吗?您会看到其他人在做一些很棒的事情:环游世界,创造发明,而我做的事情却不那么酷-我们正在做的就是利用IComparable接口。

  • 我们正在将当前实例(自己)与具有相同类型(人)的另一个对象(其他人)进行比较。

那比较器类呢?

Comparer类是实现IComparer接口的抽象基类。您应该从此类中派生出来,以进行具体的实现。无论如何,Microsoft建议您不要使用Comparer类,而不要实现IComparer接口:

我们建议您从Comparer类派生而不是实现IComparer接口,因为Comparer类提供了IComparer.Compare方法和Default属性的显式接口实现,该属性获取对象的默认比较器。

摘要

  • IComparer-排列两件事并进行比较。
  • IComparable-与FB上的其他人进行比较。

希望这些故事能帮助您记住。


1
我喜欢您说明关键概念的方式。如果您将Comparer(T)类纳入本比赛,那就更好了。甚至不包括在问题中。:)
Kevman's

4

正如其他人所说,他们做的事情不一样。

无论如何,这些天我倾向于不使用IComparer。我为什么要?它的职责(用于比较两个对象的外部实体)可以通过lambda表达式来处理,这与大多数LINQ方法的工作方式类似。编写一个快速的lambda,它将要比较的对象作为参数,并返回布尔值。而且,如果对象定义了自己的固有比较操作,则可以实现IComparable。


1
-1:返回布尔值不等于IComparer。IComparer返回的值可以小于零/零/大于零,通常用于排序。

而在需要时,您将返回一个int(或者更好的是一个enum)。这真的很重要吗?
jalf

2
您甚至可以返回布尔值,因为小于排序序列所需的唯一操作。
jalf

一个IComparer实现只需要定义一次,如果需要在更多地方使用排序逻辑,则lambda表达式将需要编写多次。
oɔɯǝɹ

oɔɯǝɹ-然后,您可以存储对作为lambda表达式编写的委托的引用,也可以重用它。
jpierson 2011年

3

IComparable说可以将一个对象与另一个对象进行比较。IComparer是可以比较任何两个项目的对象。


2

IComparer是用于对Array进行排序的接口,该接口将强制类实现Compare(T x,T y)方法,该方法将比较两个对象。实现此接口的类的实例用于Array的排序。

IComparable是在类型中实现的接口,该类型需要比较相同类型的两个对象,此可比接口将强制该类实现以下方法CompareTo(T obj)

IEqualityComparer是一个用于查找对象是否相等的接口,现在我们将在示例中看到该接口,我们必须在集合中查找对象的唯一性。该接口将实现方法Equals(T obj1,T obj2)

现在我们来看一个Example例子,我们有一个Employee类,基于这个类,我们必须创建一个Collection。现在我们有以下要求。

使用数组类2对数组进行排序。需要使用Linq进行集合:删除重复项,按从高到低的顺序排列,删除一个员工ID

abstract public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { set; get; }
}

public enum SortType
{
    ByID,
    BySalary
}

公共类EmployeeIdSorter:IComparer {public int Compare(Employee x,Employee y){if(x.Id <y.Id)return 1; 否则(x.Id> y.Id)返回-1; 否则返回0;}}

    public class EmployeeSalarySorter : IComparer<Employee>
    {
        public int Compare(Employee x, Employee y)
        {
            if (x.Salary < y.Salary)
                return 1;
            else if (x.Salary > y.Salary)
                return -1;
            else
                return 0;
        }
    }

有关更多信息,请参见以下 http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.