我正在试图弄清楚我需要实现哪些接口。它们基本上都做同样的事情。我何时才能使用其中一个?
答案 0 :(得分:91)
他们不是完全同样的事情,IComparer<T>
是在一个能够比较两个不同对象的类型上实现的,而IComparable<T>
是在能够的类型上实现的将自己与同类型的其他实例进行比较。
当我需要知道另一个实例与IComparable<T>
实例的关系时,我倾向于使用this
。 IComparer<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界面 - 比较两个人分开的人
Compare(Fred, John)
它会让更好的人出来。 IComparable怎么样? - 与其他人比较
你最近去过FB吗?你会看到其他人做很酷的事情:环游世界,创造发明,而我做的事情并不那么酷 - 我们正在做的就是利用IComparable界面。Comparer Class怎么样?
Comparer类是一个实现IComparer接口的抽象基类。您应该从这个类派生出具体的实现。无论如何,Microsoft建议您使用Comparer类而不是实现IComparer接口:
我们建议您从Comparer类派生而不是实现IComparer接口,因为Comparer类提供IComparer.Compare方法的显式接口实现和获取对象的默认比较器的Default属性。
希望故事可以帮助你记住。
答案 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