何时使用IComparable <t> Vs.的IComparer <T> </T> </T>

时间:2009-02-11 18:20:09

标签: .net icomparable icomparer

我正在试图弄清楚我需要实现哪些接口。它们基本上都做同样的事情。我何时才能使用其中一个?

8 个答案:

答案 0 :(得分:91)

他们不是完全同样的事情,IComparer<T>是在一个能够比较两个不同对象的类型上实现的,而IComparable<T>是在能够的类型上实现的将自己与同类型的其他实例进行比较。

当我需要知道另一个实例与IComparable<T>实例的关系时,我倾向于使用thisIComparer<T>对于排序集合很有用,因为IComparer<T>位于比较之外。

答案 1 :(得分:42)

当班级进行内在比较时,请使用IComparable<T>

如果需要除了类内在比较之外的比较方法(如果有),请使用IComparer<T>

答案 2 :(得分:27)

这取决于实体。例如,对于像“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;
    }
}

答案 3 :(得分:9)

这完全取决于你的类型是否可变。您应该在非可变类型上实现IComparable。请注意,如果实现IComparable,则必须覆盖Equals以及==,!=,&lt;和&gt;运算符(参见代码分析警告CA1036)。

this blog post引用Dave G:

  

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

     

由于IComparer只是一个用于在那个时间点进行排序的一次性对象,因此你的对象可以拥有你想要的任何可变语义。此外,它不需要甚至建议使用Equals,GetHashCode或== - 您可以自由地以任何方式定义它。

     

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

     

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

答案 4 :(得分:6)

通过故事进行简单解释

高中篮球。这是球队的校园选择。我希望得到团队中最高/最优/最快的人。我该怎么办?

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

  • 这让我可以比较排队的任何两个人.........基本上就是这样。 Fred vs John ..........我把它们扔进一个实现接口的具体类中。 Compare(Fred, John)它会让更好的人出来。

IComparable怎么样? - 与其他人比较

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

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

Comparer Class怎么样?

Comparer类是一个实现IComparer接口的抽象基类。您应该从这个类派生出具体的实现。无论如何,Microsoft建议您使用Comparer类而不是实现IComparer接口:

  

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

摘要

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

希望故事可以帮助你记住。

答案 5 :(得分:4)

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

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

答案 6 :(得分:3)

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

答案 7 :(得分:2)

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

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

IEqualityComparer是一个用于查找对象的接口,无论它是否为Equal,现在我们将在一个示例中看到这一点,我们必须在集合中找到Object的Distinct。该接口将实现一个方法 等于(T obj1,T obj2)

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

使用Array类对Array进行排序 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&lt; y.Id)                     返回1;                 否则if(x.Id&gt; 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