C# Проблема с IComparable при наследовании
Вопрос такой
Есть следующий код
class A : IComparable<A>, IComparable<B>
{
int IComparable<A>.CompareTo(B other)
{
//Code
}
int IComparable<B>.CompareTo(A other)
{
//Code
}
}
class B : A, IComparable<A>, IComparable<B>
{
int IComparable<A>.CompareTo(B other)
{
//Code
}
int IComparable<B>.CompareTo(A other)
{
//Code
}
}
class Program
{
static void Main()
{
List<A> a = new List<A>();
// Заполняем список рандомными элементами А и B
}
}
И при попытке отсортировать массив А, элементы сортируются не по правилам, описанным в компараторах. В чем может быть проблема?
Ответы (1 шт):
Автор решения: return
→ Ссылка
Вы не должны явно реализовывать IComparable<T>:
class A : IComparable<A>
{
public virtual int CompareTo(A? comparand) => <...>;
}
class B : A, IComparable<B>
{
public override int CompareTo(A? comparand) =>
comparand is B b ? CompareTo(b) : -1;
public virtual int CompareTo(B? comparand) => <...>;
}
Не нужно в базовом классе добавлять интерфейс для сравнения наследуемого, сам наследуемый реализует интерфейс.
Для большей ясности пример: в классе A есть поле a типа int. В классе B добавили поле b. Тогда реализация будет такой:
class A : IComparable<A>
{
public static readonly A Default = new A();
readonly int a;
public virtual int CompareTo(A? comparand)
{
comparand ??= Default;
return a.CompareTo(comparand.a);
}
}
class B : A, IComparable<B>
{
public static readonly B Default = new B();
readonly int b;
public virtual int ComareTo(B? comparand)
{
comparand ??= Default;
var cmp = b.CompareTo(comparand.b);
if (cmp != 0) return cmp;
return base.CompareTo(comparand);
}
public override int CompareTo(A? comparand) =>
comparand is B b ? CompareTo(b) :
(b == 0 ? CompareTo(comparand) : -1);
}
var a = A.Default;
var b = B.Default;
a.CompareTo(a); // 0
b.CompareTo(a); // 0
a.CompareTo(b); // 0 // так можно, т. к. идёт implicit cast `B` -> `A`