C#: uso de palabras clave virtual+anulación frente a nuevo

Resuelto i3ensays asked hace 16 años • 11 respuestas

¿Cuáles son las diferencias entre declarar un método en un tipo base " virtual" y luego anularlo en un tipo secundario usando la overridepalabra clave " " en lugar de simplemente usar la newpalabra clave " " al declarar el método coincidente en el tipo secundario?

i3ensays avatar Oct 02 '08 05:10 i3ensays
Aceptado

Siempre encuentro que cosas como esta se entienden más fácilmente con imágenes:

De nuevo, tomando el código de joseph daigle,

public class Foo
{
     public /*virtual*/ bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public /*override or new*/ bool DoSomething() { return true; }
}

Si luego llamas al código de esta manera:

Foo a = new Bar();
a.DoSomething();

NOTA: Lo importante es que nuestro objeto en realidad es un Bar, pero lo estamos almacenando en una variable de tipoFoo (esto es similar a convertirlo)

Entonces el resultado será el siguiente, dependiendo de si usaste virtual/ overrideo newal declarar tus clases.

Imagen de explicación virtual/anulación

Orion Edwards avatar Oct 01 '2008 22:10 Orion Edwards

La palabra clave "nueva" no anula, significa un nuevo método que no tiene nada que ver con el método de la clase base.

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

public class Test
{
    public static void Main ()
    {
        Foo test = new Bar ();
        Console.WriteLine (test.DoSomething ());
    }
}

Esto imprime falso, si usó anulación, habría impreso verdadero.

(Código base tomado de Joseph Daigle)

Por lo tanto, si está haciendo un polimorfismo real, SIEMPRE DEBE ANULAR . El único lugar donde necesita usar "nuevo" es cuando el método no está relacionado de ninguna manera con la versión de la clase base.

albertein avatar Oct 01 '2008 22:10 albertein

Aquí hay un código para comprender la diferencia en el comportamiento de los métodos virtuales y no virtuales:

class A
{
    public void foo()
    {
        Console.WriteLine("A::foo()");
    }
    public virtual void bar()
    {
        Console.WriteLine("A::bar()");
    }
}

class B : A
{
    public new void foo()
    {
        Console.WriteLine("B::foo()");
    }
    public override void bar()
    {
        Console.WriteLine("B::bar()");
    }
}

class Program
{
    static int Main(string[] args)
    {
        B b = new B();
        A a = b;
        a.foo(); // Prints A::foo
        b.foo(); // Prints B::foo
        a.bar(); // Prints B::bar
        b.bar(); // Prints B::bar
        return 0;
    }
}
Franci Penov avatar Oct 01 '2008 22:10 Franci Penov