首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IComparable和IComparable<T>

IComparable和IComparable<T>
EN

Stack Overflow用户
提问于 2011-09-05 02:27:10
回答 3查看 6.7K关注 0票数 38

我应该同时实现IComparable和泛型IComparable<T>吗?如果我只实现其中一个,会有什么限制吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-05 02:31:51

是的,你应该同时实现这两个。

如果你实现了一个,任何依赖于另一个的代码都将失败。

有很多代码使用IComparableIComparable<T>中的一种,但不能同时使用两者,因此实现这两种方法可以确保您的代码可以与这类代码一起工作。

票数 24
EN

Stack Overflow用户

发布于 2013-05-11 07:15:45

Oded是正确的,你应该同时实现这两个,因为有集合和其他类只依赖于其中一个实现。

但是这里有一个技巧: IComparable不应该抛出异常,而IComparable应该抛出异常。在实现IComparable时,您负责确保T的所有实例都可以相互比较。这也包括null (将null视为小于T的所有非null实例,就可以了)。

但是,通用IComparable接受System.Object,并且您不能保证所有可以想到的对象都可以与T的实例相比较。因此,如果您将一个非T实例传递给IComparable,则只需抛出System.ArgumentException。否则,将调用路由到IComparable实现。

示例如下:

代码语言:javascript
复制
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:How to Implement IComparable Interface in Base and Derived Classes时应注意的副作用的广泛分析

票数 23
EN

Stack Overflow用户

发布于 2011-09-13 12:29:44

虽然IEquatable通常不应该由未密封的类实现,因为除非实现只是调用Object.Equals (在这种情况下是没有意义的),否则这种派生与继承会有些奇怪,而泛型IComparable则出现了相反的情况。Object.Equals和IEquatable的语义意味着,无论何时定义IEquatable,它的行为都应该反映Object.Equals的行为(除了可能更快和避免装箱)。两个类型为DerivedFoo的对象在被视为DerivedFoo类型时比较相等,当被视为Foo类型的对象时也应该比较相等,反之亦然。另一方面,完全有可能两个DerivedFoo类型的对象在被视为DerivedFoo类型时排名不平等,而在被视为Foo类型时排名相同。确保这一点的唯一方法是使用IComparable。

例如,假设有一个类SchedulerEvent,其中包含字段ScheduledTime (类型为DateTime)和ScheduledAction (类型为MethodInvoker)。该类包括子类型SchedulerEventWithMessage (添加一个string类型的消息字段)和SchedulerEventWithGong (添加一个Double类型的GongVolume字段)。根据ScheduledTime,SchedulerEvent类有一个自然的排序,但是相对无序的事件完全有可能是不相等的。SchedulerEventWithMessage和SchedulerEventWithGong类之间也有自然的顺序,但与SchedulerEvent类的项相比就不一样了。

假设有两个SchedulerEventWithMessage事件X和Y被安排在同一时间,但是X.Message是"aardvark“,Y.Message是"zymurgy”。((IComparable)X).CompareTo(Y)应该报告零(因为事件具有相等的时间),但是((IComparable)X).CompareTo(Y)应该返回一个负数(因为"aardvark“在”zymurgy“之前排序)。如果类的行为不是这样的,就很难或不可能一致地对包含SchedulerEventWithMessage和SchedulerEventWithGong对象的列表进行排序。

顺便说一句,有人可能会争辩说,让IEquatable的语义只基于类型T的成员来比较对象会很有用,这样IEquatable就会检查ScheduledTime和ScheduledAction是否相等,但即使应用到SchedulerEventWithMessage或SchedulerEventWithGong上,也不会检查Message或GongVolume属性。实际上,对于IEquatable方法来说,这些都是有用的语义,我更喜欢这样的语义,但是有一个问题: Comparer.Default.GetHashCode(T)总是调用相同的函数Object.GetHashCode(),而不管类型T是什么。这极大地限制了IEquatable使用不同类型T来改变其行为的能力。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7301277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档