Разрешение метода в сравнении
-
26-09-2019 - |
Вопрос
Рассмотрим следующую базовую макет класса:
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);
}
}