我想弄清楚我需要实现哪些接口.它们基本上都做同样的事情.我何时会使用一个而不是另一个?
好吧,它们与能够比较两个不同对象的类型实现的并不完全相同,而是在能够将自己与同一类型的其他实例进行比较的类型上实现.IComparer
IComparable
IComparable
当我需要知道另一个实例如何与实例相关时,我倾向于使用this
. IComparer
对于将集合排序为IComparer
比较之外的看台非常有用.
使用IComparable
时,班里有一个内在的比较.
使用IComparer
当你想比类内在比较其他的比较方法,如果它有一个.
这取决于实体.例如,对于像"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{ public int Compare(Student x, Student y) { if (x.MathScore > y.MathScore) return 1; if (x.MathScore < y.MathScore) return -1; else return 0; } }
这一切都取决于你的类型是否可变.您应该只在非可变类型上实现IComparable.请注意,如果实现IComparable,则必须覆盖Equals以及==,!=,<和>运算符(请参阅代码分析警告CA1036).
从这篇博客文章中引用Dave G :
但正确的答案是,如果对象是可变的,则实现IComparer而不是IComparable,并在必要时将IComparer的实例传递给排序函数.
由于IComparer只是用于在该时间点进行排序的一次性对象,因此您的对象可以具有您想要的任何可变语义.此外,它不需要甚至建议使用Equals,GetHashCode或== - 您可以自由地以任何方式定义它.
最后,您可以为您的类型定义多个IComparer,以便在不同的字段或不同的规则上进行排序.这比坚持一个定义要灵活得多.
简而言之: 对值类型使用IComparable,对引用类型使用IComparer.
通过故事简单解释
高中篮球.这是球队的校园选择.我希望得到团队中最高/最优/最快的人.我该怎么办?
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上与其他人比较.
希望故事能帮助你记住.