.net 何时使用 IComparable<T> Vs。比较器<T>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/538096/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:06:42  来源:igfitidea点击:

When to use IComparable<T> Vs. IComparer<T>

.neticomparableicomparer

提问by Micah

I'm trying to figure out which of these interfaces I need to implement. They both essentially do the same thing. When would I use one over the other?

我试图弄清楚我需要实现哪些接口。他们基本上都做同样的事情。我什么时候会使用一个?

采纳答案by Andrew Hare

Well they are not quitethe same thing as IComparer<T>is implemented on a type that is capable of comparing two different objects while IComparable<T>is implemented on types that are able to compare themselves with other instances of the same type.

好吧,它们与在能够比较两个不同对象的类型上实现的东西并不完全相同IComparer<T>IComparable<T>在能够将自身与相同类型的其他实例进行比较的类型上实现。

I tend to use IComparable<T>for times when I need to know how another instance relates to thisinstance. IComparer<T>is useful for sorting collections as the IComparer<T>stands outside of the comparison.

IComparable<T>当我需要知道另一个实例如何与实例相关时,我倾向于使用thisIComparer<T>对于作为IComparer<T>比较之外的立场的集合进行排序很有用。

回答by yfeldblum

Use IComparable<T>when the class has an intrinsic comparison.

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

Use IComparer<T>when you want a comparison method other than the class' intrinsic comparison, if it has one.

IComparer<T>当您需要类的内在比较以外的比较方法时使用(如果有)。

回答by Ajay Bhosale

It depends on the entity. For example following for a class like "Student", it will make sense to have IComparable based on Name.

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

But if a teacher 'A' wants to compare students based on MathScore, and teacher 'B' wants to compare students based on EnglishScore. It will be good idea to implement IComparer separately. (More like a strategy pattern)

但是如果老师'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;
    }
}

回答by Mr. Bungle

It all depends on whether your type is mutable or not. You should onlyimplement IComparable on non-mutable types. Note that if you implement IComparable, you must override Equals, along with the ==, !=, < and > operators (see Code Analysis warning CA1036).

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

Quoting Dave G from this blog post:

引用这篇博文中的Dave G :

But the correct answer is to implement IComparer instead of IComparable if your objects are mutable, and pass an instance of the IComparer to sorting functions when necessary.

Since the IComparer is just a disposable object used for sorting at that point in time, your object can have any mutable semantics you desire. Furthermore, it doesn't require or even suggest using Equals, GetHashCode, or == - you're free to define it in any way you please.

Finally, you can define multiple IComparer's for your type for sorting on different fields or with different rules. This is much more flexible than being stuck with one definition.

In short:Use IComparable for value types and IComparer for reference types.

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

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

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

简而言之:对值类型使用 IComparable,对引用类型使用 IComparer。

回答by BKSpurgeon

Simple Explanation via a story

通过故事的简单解释

High school basketball. It's a school yard pick for the teams. I want to get the tallest/best/fastest folks on my team. What do I do?

高中篮球。这是球队的校园选秀权。我想在我的团队中找到最高/最好/最快的人。我该怎么办?

IComparer Interface- Compare two people separate people

IComparer 接口- 比较两个人分开的人

  • This allows me to compare any two guys lined up.........that's basically it. Fred vs John..........i throw them into a concrete class which implements the interface. Compare(Fred, John)and it spits out who's better.
  • 这让我可以比较任何两个排队的人......基本上就是这样。Fred vs John..........我把它们放到一个实现接口的具体类中。Compare(Fred, John)它会吐出谁更好。

What about IComparable?- Compare yourself with someone else

IComparable 呢?- 把自己和别人比较

Have you been on FB recently? You see other folks doing cool things: travelling the world, creating inventions, while I'm doing something not quite as cool - well what we are doing is making use of the IComparable interface.

你最近上FB了吗?你看到其他人在做很酷的事情:环游世界、创造发明,而我正在做一些不太酷的事情——我们正在做的是利用 IComparable 接口。

  • We are comparing the current instance (yourself) with another object (someone else) which is of the same type (person).
  • 我们正在将当前实例(您自己)与另一个相同类型(人)的对象(其他人)进行比较。

What about the Comparer Class?

比较器类呢?

The Comparer class is an abstract base class which implements the IComparer interface. You should derive from this class to have a concrete implementation. anyways, Microsoft recommends that you DO use the Comparer class rather than implement the IComparer interface:

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

We recommend that you derive from the Comparer class instead of implementing the IComparer interface, because the Comparer class provides an explicit interface implementation of the IComparer.Compare method and the Default property that gets the default comparer for the object.

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

Summary

概括

  • IComparer - line up two things and compare.
  • IComparable - compare yourself with others on FB.
  • IComparer - 排列两件事并进行比较。
  • IComparable - 将自己与 FB 上的其他人进行比较。

Hope the stories help you remember.

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

回答by jalf

As others have said, they don't do the same thing.

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

In any case, these days I tend not to use IComparer. Why would I? Its responsibility (an external entity used to compare two objects) can be handled much cleaner with a lambda expression, similar to how most of LINQ's methods work. Write a quick lambda which takes the objects to compare as arguments, and returns a bool. And if the object defines its own intrinsic compare operation, it can implement IComparable instead.

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

回答by Neil Barnwell

IComparable says an object can be compared with another. IComparer is an object that can compare any two items.

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

回答by Rajesh G

IComparer is a interface which is used to sort the Array, this interface will force the class to implement the Compare(T x,T y) method, which will compare the two objects. The instance of the class which implemented this interface is used in the sorting of the Array.

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

IComparable is a interface is implemented in the type which needs to compare the two objects of the same type, This comparable interface will force the class to implement the following method CompareTo(T obj)

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

IEqualityComparer is a interface which is used to find the object whether it is Equal or not, Now we will see this in a sample where we have to find the Distinct of a Object in a collection. This interface will implement a method Equals(T obj1,T obj2)

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

Now we take a Example we have a Employee class , based on this class we have to create a Collection. Now we have the following requirements.

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

Sort the Array using Array class 2. Need an collection using Linq : Remove the Duplicate, Order by higher to lower, Remove one employee id

使用 Array 类 2 对 Array 进行排序。需要使用 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
}

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

公共类 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;
        }
    }

For more info refere below http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html

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