Question

J'ai une classe de base simple et classe dérivée:

class Base
{
    public virtual void Write(int value)
    {
        Console.WriteLine("base int: {0}", value);
    }

    public virtual void Write(string value)
    {
        Console.WriteLine("base string: {0}", value);
    }
}

class Derived : Base
{
    public override void Write(int value)
    {
        Console.WriteLine("derived int: {0}", value);
    }

    public virtual void Write(IEnumerable enumerable)
    {
        Console.WriteLine("derived IEnumerable: {0}", enumerable);
    }

    public virtual void Write(object o)
    {
        Console.WriteLine("derived obj: {0}", o);
    }
}

Si je lance ceci:

    static void Main(string[] args)
    {
        Derived d = new Derived();
        Console.WriteLine("derived:");
        d.Write(42);
        d.Write("hello");

        Console.WriteLine("base:");
        Base b = d;
        b.Write(42);
        b.Write("hello");
    }

Je reçois:

derived:
derived obj: 42
derived IEnumerable: hello
base:
derived int: 42
base string: hello

Mais je me attends "b.Write (42)" et "d.Write (42)" identiques. La même chose pour le cas de la chaîne.

Qu'est-ce que je ne comprends? Comment puis-je obtenir le comportement d'être ce que je me attends donné la contrainte que je ne peux pas modifier « Base »?

UPDATE : Voir d'Eric après.

Était-ce utile?

La solution

Cela se produit parce que C # considère les méthodes déclarées dans un type avant toute autre chose, y compris les méthodes de remplacement. Voir: Section 7.3 du C # spec .

explique assez bien et explique aussi les raisons.

  

Ce comportement très unintuitive se justifie par les deux règles suivantes:

     
      
  1. Si oui ou non une méthode est surchargée est un détail de mise en œuvre   qui devraient être autorisés à changer   sans casser le code client.
  2.   
  3. Les modifications apportées à une classe de base qui ne cassent pas une classe héritée devrait   ne cassera pas les clients du hérité   classe.
  4.   

Autres conseils

chaîne peut être implicitement à IEnumerable (de caractères), mais son ToString () retourne toujours la chaîne. Par conséquent, la résolution est b.Write("hello"); méthode virtuelle IEnumerable parce qu'il est plus proche du type référencé.

Je vérifierai, mais si vous remplacez la surcharge de chaîne dans votre classe dérivée, il pourrait résoudre correctement dans le code client.

EDIT

Je me trompais, primordiale ne permet pas. Vous pourriez avoir à renommer vos virtuals dérivées pour éviter la collision.

EDIT II

Le travail ci-dessous est, mais il est uber hackey, et je ne l'aime pas. Ajouter cette méthode à Derived:

public new void Write(string value)
{
    base.Write(value);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top