nueva palabra clave en la firma del método


Mientras realizaba una refactorización, terminé creando un método como el siguiente ejemplo. El tipo de datos ha sido cambiado por simplicidad.

I anterior tenía una declaración de asignación como esta:

MyObject myVar = new MyObject();

Fue refactorizado a esto por accidente:

private static new MyObject CreateSomething()
{
  return new MyObject{"Something New"};
}

Esto fue el resultado de un error de cortar/pegar de mi parte, pero la palabra clave new en private static new es válida y compila.

Pregunta: ¿Qué significa la palabra clave new en una firma de método? Supongo que es ¿algo introducido en C # 3.0?

¿En qué se diferencia esto de override?

Author: Filburt, 2009-06-18

8 answers

Nueva referencia de palabra clave de MSDN:

Referencia MSDN

Aquí hay un ejemplo que encontré en la red de un MVP de Microsoft que tenía sentido: Enlace al original

public class A
{
   public virtual void One();
   public void Two();
}

public class B : A
{
   public override void One();
   public new void Two();
}

B b = new B();
A a = b as A;

a.One(); // Calls implementation in B
a.Two(); // Calls implementation in A
b.One(); // Calls implementation in B
b.Two(); // Calls implementation in B

Override solo se puede usar en casos muy específicos. De MSDN:

No se puede anular un no virtual o método estático. La base reemplazado el método debe ser virtual, abstracto o anular.

Así que la palabra clave' new 'es necesaria para permitirle 'override' métodos no virtuales y estáticos.

 86
Author: Kelsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-18 19:40:40

No, en realidad no es "nuevo" (perdón por el juego de palabras). Se utiliza básicamente para "ocultar" un método. IE:

public class Base
{
   public virtual void Method(){}
}

public class Derived : Base
{
   public new void Method(){}
}

Si luego haces esto:

Base b = new Derived();
b.Method();

El método en la Base es el que será llamado, NO el que está en el derivado.

Algo más de información: http://www.akadia.com/services/dotnet_polymorphism.html

Re your edit: En el ejemplo que di, si fueras a " override "en lugar de usar" new " entonces cuando llames a b.Method (); la clase derivada Método sería llamado debido al polimorfismo.

 55
Author: BFree,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-18 18:24:37

Como otros explicaron, se usa para ocultar un método existente. Es útil para sobreescribir un método que no es virtual en la clase padre.

Tenga en cuenta que crear un miembro "nuevo" no es polimórfico. Si envía el objeto al tipo base, no utilizará el miembro del tipo derivado.

Si tienes una clase base:

public class BaseClass
{
    public void DoSomething() { }
}

Y luego la clase derivada:

public class DerivedType : BaseClass
{
    public new void DoSomething() {}

}

Si declaras un tipo de DerivedType y luego lo lanzas, el método DoSomething() no es polimórfico, lo hará llame al método de la clase base, no al derivado.

BaseClass t = new DerivedType();
t.DoSomething();// Calls the "DoSomething()" method of the base class.
 19
Author: Dan Herbert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-21 17:38:13

De los documentos:

Si el método en la clase derivada está precedido por la palabra clave new, el método se define como independiente del método en la clase base.

Lo que esto significa en la práctica:

Si hereda de otra clase y tiene un método que comparte la misma firma, puede definirlo como 'nuevo' para que sea independiente de la clase padre. Esto significa que si usted tiene una referencia a la clase' padre ' entonces esa implementación será ejecutada, si usted tiene una referencia a la clase hija entonces esa implementación será ejecutada.

Personalmente trato de evitar la palabra clave 'new', ya que normalmente significa que tengo mi jerarquía de clases equivocada, pero hay momentos en que puede ser útil. Un lugar es para el control de versiones y la compatibilidad con versiones anteriores.

Hay mucha información en el MSDN para esto.

 6
Author: jonnii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-30 16:15:24

Significa que el método reemplaza un método con el mismo nombre heredado por la clase base. En tu caso, probablemente no tengas un método con ese nombre en la clase base, lo que significa que la nueva palabra clave es totalmente superflua.

 3
Author: Robin Clowers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-18 18:16:15

En pocas palabras NOT no es necesario, no cambia el comportamiento, y es PURAMENTE allí para la legibilidad.

Es por eso que en VS verá un poco torcido, sin embargo, su código se compilará y se ejecutará perfectamente bien y como se espera.

Uno tiene que preguntarse si realmente valió la pena crear la palabra clave new cuando todo lo que significa es que el desarrollador reconoce " Sí, sé que estoy ocultando un método base, sí sé que no estoy haciendo nada relacionado con virtual o overriden (polimorfismo) -- Realmente quiero crear su propio método".

Es un poco extraño para mí, pero tal vez solo porque vengo de un fondo Java y hay esta diferencia fundamental entre C# herencia y Java: En Java, los métodos son virtuales por defecto a menos que se especifique por final. En C#, los métodos son finales/concretos por defecto a menos que se especifique por virtual.

 3
Author: mmcrae,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-25 20:48:43

De MSDN :

Utilice el nuevo modificador para ocultar explícitamente un miembro heredado de un clase base. Para ocultar un miembro heredado, declararlo en el derivado clase usando el mismo nombre, y modifíquelo con el nuevo modificador.

 1
Author: Doug R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-30 16:07:07

Ten cuidado con esto.
Tiene un método definido en una interfaz que se implementa en una clase base. A continuación, crea una clase derivada que oculta el método de la interfaz, pero no declara específicamente que la clase derivada implemente la interfaz. Si luego llama al método a través de una referencia a la interfaz, se llamará al método de la clase base. Sin embargo, si su clase derivada implementa específicamente la interfaz, entonces su método se llamará cualquiera que sea el tipo de se utiliza la referencia.

interface IMethodToHide
{
    string MethodToHide();
}

class BaseWithMethodToHide : IMethodToHide
{
    public string MethodToHide()
    {
        return "BaseWithMethodToHide";
    }
}

class DerivedNotImplementingInterface   : BaseWithMethodToHide
{
    new public string MethodToHide()
    {
        return "DerivedNotImplementingInterface";
    }
}

class DerivedImplementingInterface : BaseWithMethodToHide, IMethodToHide
{
    new public string MethodToHide()
    {
        return "DerivedImplementingInterface";
    }
}

class Program
{
    static void Main()
    {
        var oNoI = new DerivedNotImplementingInterface();
        IMethodToHide ioNoI = new DerivedNotImplementingInterface();

        Console.WriteLine("reference to the object type DerivedNotImplementingInterface calls the method in the class " 
            + oNoI.MethodToHide());
        // calls DerivedNotImplementingInterface.MethodToHide()
        Console.WriteLine("reference to a DerivedNotImplementingInterface object via the interfce IMethodToHide calls the method in the class " 
            + ioNoI.MethodToHide());
        // calls BaseWithMethodToHide.MethodToHide()
        Console.ReadLine();

        var oI = new DerivedImplementingInterface();
        IMethodToHide ioI = new DerivedImplementingInterface();

        Console.WriteLine("reference to the object type DerivedImplementingInterface calls the method in the class " 
            + oI.MethodToHide());
        // calls DerivedImplementingInterface.MethodToHide()
        Console.WriteLine("reference to a DerivedImplementingInterface object via the interfce IMethodToHide calls the method in the class " 
            + ioI.MethodToHide());
        // calls DerivedImplementingInterface.MethodToHide()
        Console.ReadLine();

    }
}
 0
Author: Overfilledwaistcoat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-31 18:01:41