Вопрос

Рассмотрим следующую базовую макет класса:

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());

Я ожидал, что сравнительной способ призвать метод deried.compareto в тех ситуациях, когда это параметры X и Y получены экземпляры.

Однако это не так, и вместо этого называется Base.comPareTo, и я продолжаю удивляться, почему. Я не могу вычесть это поведение с моим основным пониманием правил разрешения перегрузки, как описано в спецификации языка C #.

Может кто-нибудь пролить свет на это для меня?

Это было полезно?

Решение

Base ничего не знает о своих полученных классах - так в Base есть только один CompareTo Метод, и это называется безоговорочно.

Дело в том, что разрешение перегрузки происходит в время компиляции где нет информации о фактическом типе Base Ссылки доступны. Тебе следует переопределять метод внутри Derived, нет перегрузка Это:

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

И дополнительно отметьте Base.CompareTo метод virtual.

Обратите внимание, что это не реализует IComparable<Derived> больше. Ты сможешь также Сделайте это, но для своей цели, которая не связана.

Другие советы

Разрешение перегрузки не то, что здесь происходит. У вас есть два независимых метода: их полные имена IComparable<Base>.CompareTo а также IComparable<Derived>.CompareTo.

Единственный, кто BaseComparer знает, как позвонить это IComparable<Base>.CompareTo. Отказ Это ничего не знает о IComparable<Derived>.

В вашей заявке есть смысл сравнивать Base с А. Derived - то есть, могу сказать, что Base приходит до или после Derived?

  • Если это так, вам было бы лучше остаться только с IComparable<Base>, или даже неребные IComparable, и будьте готовы проверить типы в подклассах
  • Если нет, вы должны рассмотреть Base Аннотация и только реализация IComparable<T> на листовых классах

IComparable<Base> а также IComparable<Derived> два разных типа, поэтому два метода CompareTo в Derived сопоставлены на две разные слоты. CompareTo вызывается BaseComparer Способ звонков IComparable<Base>. Отказ Вы можете обозначить CompareTo(Base) в Base так как virtual и переопределить его в Derived получить (частично) ожидаемое поведение.

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);
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top