代码之家  ›  专栏  ›  技术社区  ›  Anton

比较器中的方法分辨率

  •  1
  • Anton  · 技术社区  · 14 年前

    考虑以下基本类布局:

    public class Base : IComparable<Base>
    {
      public int CompareTo(Base other)
      {
        //Do comparison
      }
    }
    
    public class Derived : Base, IComparable<Derived>
    {
      public int CompareTo(Derived other)
      {
        //Do comparison
      }  
    }
    
    public class BaseComparer : IComparer<Base>
    {
      public int Compare(Base x, Base y)
      {
       return x.CompareTo(y);
      }
    }
    

    然后使用如下所示:

    List<Base> thingies = new List<Base>
    {
      new Base(),
      new Derived(),
      new Derived()
    };
    
    thingies.Sort(new BaseComparer());
    

    我希望比较器在X和Y参数都是派生实例的情况下调用Derived.CompareTo方法。

    但是,这不是case和base.compareto,而是被调用的,我一直在想为什么。我似乎无法用我对C语言规范中描述的过载解决规则的基本理解来推断这种行为。

    有人能帮我解释一下吗?

    3 回复  |  直到 14 年前
        1
  •  5
  •   Konrad Rudolph    14 年前

    Base 不知道它的派生类 基地 只有_ CompareTo 方法,它将无条件地被调用。

    重点是过载分辨率发生在 编译时间 如果没有关于 基地 参考资料可用。你需要 重写 中的方法 Derived 不是 超载 它:

    public class Derived : Base
    {
      public override int CompareTo(Base other)
      {
        //Do comparison
      }  
    }
    

    另外,标记 Base.CompareTo 方法 virtual .

    注意,这并不能实现 IComparable<Derived> 再。你可以 这样做,但为了你的目的,这是无关的。

        2
  •  1
  •   Tim Robinson    14 年前

    过载分辨率不是这里发生的事情。你有两个独立的方法:它们的全名是 IComparable<Base>.CompareTo IComparable<Derived>.CompareTo .

    唯一一个 BaseComparer 知道如何打电话是 IComparable<Base>。比较对象 . 它什么都不知道 IComparable<Derived> .

    在应用程序中,比较 Base 用一个 Derived --也就是说, 基地 在…之前或之后 衍生的 ?

    • 如果是这样的话,你最好还是呆在一起 IComparable<Base> 甚至是非一般的 IComparable 并准备检查子类中的类型
    • 如果没有,你应该考虑 基地 摘要,并且只实现 IComparable<T> 叶类
        3
  •  1
  •   Konrad Rudolph    14 年前

    IComparable<Base> IComparable<Derived> 是两种不同的类型,所以有两种方法 CompareTo 在里面 Derived 映射到两个不同的槽上。 并列 被调用 BaseComparer 调用方法 iComparable<Base> . 你可以表示 CompareTo(Base) 在里面 Base 作为 virtual 并在 衍生的 获取(部分)预期行为。

    public class Base : IComparable<Base>
    {
        public virtual int CompareTo(Base other)
        {
            // do comparison
        }
    }
    
    public class Derived : Base, IComparable<Derived>
    {
        public int CompareTo(Derived other)
        {
            // do comparison
        }
    
        public override int CompareTo(Base other)
        {
            if (other is Derived)
                return CompareTo((Derived) other);
            return base.CompareTo(other);
        }
    }