Domanda

Ho una semplice base di partenza della classe e classe derivata:

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);
    }
}

Se eseguo questo:

    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");
    }

Ottengo:

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

Ma io sono in attesa". b.Scrivere(42)" e "d.Scrivere(42)" per essere identici.Lo stesso per la stringa caso.

Che cosa sono io a non capire?Come posso ottenere il comportamento da ciò che mi aspetto, dato il vincolo che non posso modificare "Base"?

AGGIORNAMENTO:Vedere Eric post.

È stato utile?

Soluzione

Questo accade perché C # considera metodi dichiarati in un tipo prima di ogni altra cosa, compresi i metodi di override. Vedere: Sezione 7.3 del C # spec .

spiega abbastanza bene , e spiega anche le ragioni.

  

Questo comportamento altamente intuitivo è giustificato per le seguenti due regole:

     
      
  1. o meno un metodo viene sovrascritto è un dettaglio di implementazione   che dovrebbe essere consentito di cambiare   senza rompere il codice del client.
  2.   
  3. Le modifiche a una classe di base che non si rompono una classe ereditata dovrebbe   Non rompere i clienti del ereditata   Classe.
  4.   

Altri suggerimenti

la stringa può essere implicitamente il cast IEnumerable (di caratteri), ma la sua ToString() ritorna la stringa.Pertanto, b.Write("hello"); è la risoluzione IEnumerable metodo virtuale, perché è più vicino al tipo per riferimento.

Cercherò di verificare, ma se sostituisci la stringa di sovraccarico nella classe derivata, potrebbe risolvere correttamente il codice del client.

MODIFICA

Ho sbagliato, l'override non aiuta.Potrebbe essere necessario rinominare il derivato virtuali per evitare la collisione.

EDIT II

Al di sotto di un lavoro, ma è uber hackey, e non mi piace.Aggiungere questo metodo per Derived:

public new void Write(string value)
{
    base.Write(value);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top