【发布时间】:2009-02-11 18:20:08
【问题描述】:
我正在尝试找出我需要实现哪些接口。他们基本上都做同样的事情。我什么时候会使用其中一个?
【问题讨论】:
-
很好的例子和解释在这里找到:support.microsoft.com/nl-nl/help/320727/…
标签: .net icomparable icomparer
我正在尝试找出我需要实现哪些接口。他们基本上都做同样的事情。我什么时候会使用其中一个?
【问题讨论】:
标签: .net icomparable icomparer
它们并不完全与IComparer<T> 是在能够比较两个不同对象的类型上实现的,而IComparable<T> 是在能够比较自身的类型上实现的其他同类型的实例。
当我需要知道另一个实例与this 实例的关系时,我倾向于使用IComparable<T>。 IComparer<T> 可用于对集合进行排序,因为 IComparer<T> 位于比较之外。
【讨论】:
IComparable 我是可比的>。这意味着我可以与其他东西进行比较。并把IComparer读作我是一个比较者,我只是比较,这意味着我比较了一些东西。
当类具有内在比较时,使用IComparable<T>。
如果您需要类的内在比较以外的比较方法(如果有的话),请使用 IComparer<T>。
【讨论】:
这取决于实体。例如,对于像“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;
}
}
【讨论】:
通过故事进行简单解释
高中篮球。这是球队的校园选秀权。我想让我的团队中最高/最好/最快的人。我该怎么办?
IComparer 界面 - 比较两个不同的人
Compare(Fred, John) 它会吐出谁更好。 IComparable 怎么样? - 将自己与其他人进行比较
你最近上FB了吗?你看到其他人在做很酷的事情:环游世界,创造发明,而我做的事情并不那么酷 - 我们正在做的是利用 IComparable 接口。
比较器类呢?
Comparer 类是实现 IComparer 接口的抽象基类。您应该从此类派生以获得具体的实现。无论如何,Microsoft 建议您使用 Comparer 类而不是实现 IComparer 接口:
我们建议您从 Comparer 类派生而不是实现 IComparer 接口,因为 Comparer 类提供了 IComparer.Compare 方法的显式接口实现以及获取对象默认比较器的 Default 属性。
希望这些故事能帮助你记住。
【讨论】:
这完全取决于您的类型是否可变。您应该仅在非可变类型上实现 IComparable。请注意,如果您实现 IComparable,则必须重写 Equals 以及 ==、!=、 运算符(请参阅代码分析警告 CA1036)。
引用 this blog post 的 Dave G:
但正确的答案是如果您的对象是可变的,则实现 IComparer 而不是 IComparable,并在必要时将 IComparer 的实例传递给排序函数。
由于 IComparer 只是用于在该时间点进行排序的一次性对象,因此您的对象可以具有您想要的任何可变语义。此外,它不需要甚至不建议使用 Equals、GetHashCode 或 == - 您可以随意定义它。
最后,您可以为您的类型定义多个 IComparer,以便按不同的字段或使用不同的规则进行排序。这比坚持一个定义要灵活得多。
简而言之: 对值类型使用 IComparable,对引用类型使用 IComparer。
【讨论】:
正如其他人所说,他们不会做同样的事情。
无论如何,这些天我倾向于不使用 IComparer。我为什么要?它的职责(用于比较两个对象的外部实体)可以使用 lambda 表达式更清晰地处理,类似于大多数 LINQ 方法的工作方式。编写一个快速 lambda,它将要比较的对象作为参数,并返回一个布尔值。如果对象定义了自己的内在比较操作,它可以实现 IComparable。
【讨论】:
IComparer 是一个用于对 Array 进行排序的接口,该接口将强制类实现 Compare(T x,T y) 方法,它将比较两个对象。实现该接口的类的实例用于数组的排序。
IComparable是在需要比较同一类型的两个对象的类型中实现的接口,这个可比较的接口会强制类实现下面的方法CompareTo(T obj)
IEqualityComparer 是一个用于查找对象是否相等的接口,现在我们将在示例中看到这一点,我们必须在集合中查找对象的 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 { 公共 int 比较(员工 x,员工 y) { 如果 (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
【讨论】:
IComparable 表示一个对象可以与另一个对象进行比较。 IComparer 是一个可以比较任意两个项目的对象。
【讨论】: