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?

Était-ce utile?

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 le IComparable 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 œuvre IComparable<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);
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top