résolution Procédé Comparer
-
26-09-2019 - |
Question
tenir compte de la mise en page de la classe de base suivante:
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);
}
}
et puis en utilisant ceux comme suit:
List<Base> thingies = new List<Base>
{
new Base(),
new Derived(),
new Derived()
};
thingies.Sort(new BaseComparer());
Je me attendais à la demande Comparer la méthode Derived.CompareTo dans les situations où les deux ses paramètres x et y sont des instances DÉRIVÉS.
Cependant, ce n'est pas le cas et Base.CompareTo est appelé à la place et je me demande pourquoi. Je ne peux pas sembler déduire ce comportement avec ma compréhension de base des règles de résolution de surcharge comme décrit dans la spécification du langage C #.
Quelqu'un peut-il faire la lumière sur ce pour moi?
La solution
Base
ne sait rien de ses classes dérivées. - donc dans Base
il n'y a que un méthode CompareTo
, et qui est appelé inconditionnellement
Le point est que la résolution de surcharge arrive à compilation où il n'y a pas d'informations sur le type réel de références Base
disponibles. Vous devez override la méthode Derived
, pas surcharge il:
public class Derived : Base
{
public override int CompareTo(Base other)
{
//Do comparison
}
}
Et en outre marquer la méthode Base.CompareTo
virtual
.
Notez que cela ne met pas en œuvre IComparable<Derived>
plus. Vous pouvez aussi faire, mais pour votre but qui est sans rapport avec.
Autres conseils
Résolution de surcharge n'est pas ce qui se passe ici. Vous avez deux méthodes indépendantes. Leur nom complet sont IComparable<Base>.CompareTo
et IComparable<Derived>.CompareTo
Le seul qui sait BaseComparer
comment appeler est IComparable<Base>.CompareTo
. Il ne sait rien IComparable<Derived>
.
Dans votre application, est-il logique de comparer un Base
avec un Derived
- c'est peut dire qu'un Base
vient avant ou après un Derived
- Si oui, vous feriez mieux de rester avec seulement
IComparable<Base>
, ou même leIComparable
non générique, et être prêt à vérifier les types dans les sous-classes - Dans le cas contraire, vous devriez envisager de faire abstraction de
Base
, et que la mise en œuvreIComparable<T>
sur les classes de feuilles
IComparable<Base>
et IComparable<Derived>
sont de deux types différents, de sorte que deux méthodes CompareTo
en Derived
sont mappés sur deux emplacements différents. CompareTo
invoqué par BaseComparer
appelle la méthode de IComparable<Base>
. Vous pouvez désigner CompareTo(Base)
dans Base
comme virtual
et le remplacer dans Derived
pour obtenir (partiellement) le comportement attendu.
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);
}
}