代码之家  ›  专栏  ›  技术社区  ›  Luc Touraille

实现IComparable<notself>

  •  6
  • Luc Touraille  · 技术社区  · 16 年前

    这可能是一个微不足道的问题,但我没有找到关于这方面的任何信息:使T类型实现是“有害的”还是被认为是不好的实践? IComparable<S> (T和S是两种不同的类型)?

    例子:

    class Foo : IComparable<int>
    {
        public int CompareTo(int other)
        {
            if (other < i) return -1;
            if (other > i) return 1;
    
            return 0;
        }
    
        private int i;
    }
    

    应该避免这种代码吗?如果是,为什么?

    3 回复  |  直到 14 年前
        1
  •  6
  •   Jon Skeet    16 年前

    我至少会认为这是“奇怪的”——特别是在那一点上,比较不会是对称的,这通常是正常比较契约的一部分。

    如果有一种特定的情况比任何其他实现你想要做的事情都简单,那就没问题了——但我不能说我从来没有遇到过这种情况。类似这样的比较几乎总是用于对同构集合或类似集合进行排序。

    你有没有想过一个特殊的情况,或者只是一个“为了兴趣”的问题?

        2
  •  2
  •   Yousf    16 年前

    实现这样的事情是一种幻想。但这不是一个好的做法。

    假设您看到如下代码:

    Foo x = new Foo();
    
    if( x.compareTo(15) > 0)
    {
      //blah blah
    }
    

    你会说“哦,天哪!如何将15与x进行比较?”是吗? 这将降低代码的可读性。

    最好添加如下比较函数: 公共int ismorethanprivatei(int x);

        3
  •  1
  •   supercat    14 年前

    我可以看到一个用于比较不同类的对象的用法,但是我认为不可替代的(t)是正确的基础。要使这种比较真正起作用,对象必须具有公共规范形式,这意味着它们都是从公共祖先派生的,或者实现公共接口。我进一步建议这个公共基础包括一个secondchancecompareto方法,如果它不能识别 精确的 将自身传递到传入对象的secondchanceCompare方法。

    作为这种类型的东西可能有用的例子,想象一下存储字符串的一系列类;一个字符串可能存储为一个简单的字符串对象,但是一些字符串可能存储为一个字符和重复计数,另一些字符串可能存储为对一个较长的字符串的引用以及起始偏移量和长度等。它非常有用。D可以通过将两个字符串对象转换为“string”类型,然后进行比较来比较它们,但在许多情况下存在更好的比较方法。例如,如果一个字符串存储为“character'z'repeated 100000 times”,而另一个字符串存储为“literal string'dog'”,则前一个字符串可以通过观察到后一个字符串的第一个字符小于“z”,将自身与后者进行比较。

    请注意,基本的“literal string”对象可能不知道如何将自身与“repeated character”字符串对象进行比较,除非将后者转换为literal string(这是一个昂贵的操作),但它可以调用后者的“secondchanceCompare”方法,该方法将知道如何将自身与literal string进行比较。

    推荐文章