Pregunta

Tengo una clase base simple y clase derivada:

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 me quedo esto:

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

Me sale:

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

Pero estoy esperando "b.Write (42)" y "d.Write (42)" a ser idénticos. Lo mismo para el caso de cuerdas.

¿Qué no estoy entendiendo? ¿Cómo puedo obtener el comportamiento a ser lo que yo estoy esperando dada la limitación de que no puedo modificar "base"?

Actualizar de Eric poste .

¿Fue útil?

Solución

Esto sucede debido a que C # considera métodos declarados en un tipo antes de cualquier otra cosa, incluyendo los métodos de anulación. Ver: Sección 7.3 de la especificación C # .

lo explica bastante bien y también explica las razones.

  

Este comportamiento altamente intuitivo es justificado por las dos reglas siguientes:

     
      
  1. Sea o no se anula un método es un detalle de implementación   que se debe permitir a cambiar   sin romper el código del cliente.
  2.   
  3. Los cambios en una clase base que no se rompen una clase heredada debe   No romper clientes de la herencia   clase.
  4.   

Otros consejos

cadena pueden convertirse implícitamente a IEnumerable (de caracteres), pero su ToString () devuelve la cadena todavía. Por lo tanto, b.Write("hello"); se resolver el método virtual IEnumerable porque está más cerca del tipo referenciado.

Voy a verificar, pero si se ha sobrepasado la sobrecarga de cadena en su clase derivada, se podría resolver correctamente en el código de cliente.

Editar

Me equivoqué, primordial no ayuda. Puede que tenga que cambiar el nombre de los virtuales derivados para evitar la colisión.

EDITAR II

La continuación funciona, pero es súper hackey, y no me gusta. Añadir este método a Derived:

public new void Write(string value)
{
    base.Write(value);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top