![](/img/trans.png)
[英]Difference between IComparable and IComparable<T> in this search method
[英]IComparable and IComparable<T>
我应该同时实现IComparable
和泛型IComparable<T>
吗? 如果仅实现其中之一,是否有任何限制?
Oded是正确的,您应该同时实现这两者,因为有些集合和其他类仅依赖于其中一种实现。
但是,这里有一个窍门:IComparable <T>不应引发异常,而IComparable则应引发异常。 在实现IComparable <T>时,您负责确保可以将T的所有实例相互比较。 这也包括null(将null处理为小于T的所有非null实例,那么就可以了)。
但是,常规IComparable接受System.Object,并且不能保证所有可想到的对象都可以与T的实例进行比较。因此,如果将非T实例传递给IComparable,则只需抛出System.ArgumentException。 否则,将调用路由到IComparable <T>实现。
这是示例:
public class Piano : IComparable<Piano>, IComparable
{
public int CompareTo(Piano other) { ... }
...
public int CompareTo(object obj)
{
if (obj != null && !(obj is Piano))
throw new ArgumentException("Object must be of type Piano.");
return CompareTo(obj as Piano);
}
}
此示例是更长篇文章的一部分,其中包含对副作用的广泛分析,在实现IComparable <T>时应注意: 在基类和派生类中如何实现IComparable <T>接口
是的,您应该同时实现。
如果实现一个,则任何依赖于另一个的代码都将失败。
有很多使用IComparable
或IComparable<T>
的代码,但不能同时使用两者,因此同时实现这两个代码可确保您的代码将与此类代码一起使用。
尽管IEquatable <T>通常不应由未密封的类实现,因为除非实现只调用Object.Equals(在这种情况下将是毫无意义的),否则这种派生会在继承中扮演奇怪的角色,而与之相反的情况是通用IComparable <T >。 Object.Equals和IEquatable <T>的语义意味着,每当定义IEquatable <T>时,其行为都应与Object.Equals相同(除了可能更快并且避免装箱)。 当被视为DerivedFoo类型时比较相同的两个DerivedFoo类型对象也应在被视为Foo类型对象时比较相等,反之亦然。 另一方面,完全有可能两个DerivedFoo类型的对象在被视为DerivedFoo类型时排名不相等,而在被视为Foo类型时也应排名相等。 确保这一点的唯一方法是使用IComparable <T>。
例如,假设有一个SchedulerEvent类,它包含ScheduledTime(DateTime类型)和ScheduledAction(MethodInvoker类型)字段。 该类包括子类型SchedulerEventWithMessage(添加了字符串类型的Message字段)和SchedulerEventWithGong(添加了Double类型的GongVolume字段)。 SchedulerEvent类按ScheduledTime具有自然排序,但相对于彼此无序的事件完全不相等是完全可能的。 SchedulerEventWithMessage和SchedulerEventWithGong类之间也具有自然顺序,但与SchedulerEvent类的项目相比则没有。
假设有两个SchedulerEventWithMessage事件X和Y分别安排在同一时间,但X.Message是“ aardvark”,而Y.Message是“ zymurgy”。 ((IComparable <SchedulerEvent>)X).CompareTo(Y)应该报告零(因为事件具有相等的时间),但是(((IComparable <SchedulerEventWithMessage>)X).CompareTo(Y)应该返回负数(因为“ aardvark”在“ zymurgy”之前排序)。 如果该类不以这种方式运行,则很难或不可能一致地对包含SchedulerEventWithMessage和SchedulerEventWithGong对象的混合物的列表进行排序。
顺便说一句,可能有人认为仅使IEquatable <T>的语义仅基于类型T的成员比较对象就很有用,因此IEquatable <SchedulerEvent>会检查ScheduledTime和ScheduledAction是否相等,即使应用时也是如此。到SchedulerEventWithMessage或SchedulerEventWithGong不会检查Message或GongVolume属性。 确实,那些对于IEquatable <T>方法将是有用的语义,而我更喜欢这种语义,但是对于一个问题:Comparer <T> .Default.GetHashCode(T)始终调用相同的函数Object.GetHashCode()而不管类型T。这极大地限制了IEquatable <T>随不同类型T改变其行为的能力。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.