web-dev-qa-db-fra.com

nouveau mot clé dans la signature de méthode

En effectuant une refactorisation, j'ai fini par créer une méthode comme celle présentée ci-dessous. Le type de données a été modifié pour des raisons de simplicité.

J'ai eu précédemment une déclaration de mission comme celle-ci:

MyObject myVar = new MyObject();

Il a été refait à cela par accident:

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

Cela est dû à une erreur de copier/coller de ma part, mais le mot clé new dans private static new est valide et compile.

Question : Que signifie le mot clé new dans une signature de méthode? Je suppose que c'est quelque chose d'introduit dans C # 3.0? 

Comment cela diffère-t-il de override?

105
p.campbell

Nouvelle référence de mot clé à partir de MSDN:

Référence MSDN

Voici un exemple que j'ai trouvé sur le net à partir d'un MVP Microsoft qui était logique: Lien vers l'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

La dérogation ne peut être utilisée que dans des cas très spécifiques. De MSDN:

Vous ne pouvez pas remplacer un non-virtuel ou méthode statique. La base remplacée méthode doit être virtuelle, abstraite ou passer outre.

Le nouveau mot-clé est donc nécessaire pour vous permettre de «remplacer» les méthodes non virtuelles et statiques.

90
Kelsey

Non, ce n'est pas "nouveau" (pardonnez le jeu de mots). Il est essentiellement utilisé pour "cacher" une méthode. C'EST À DIRE:

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

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

Si vous faites alors ceci:

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

La méthode dans la base est celle qui sera appelée, PAS celle dans la dérivée.

Quelques informations supplémentaires: http://www.akadia.com/services/dotnet_polymorphism.html

Re votre édition: Dans l'exemple que j'ai donné, si vous deviez "écraser" au lieu d'utiliser "new", alors vous appelez b.Method (); la méthode de la classe dérivée serait appelée à cause du polymorphisme.

57
BFree

Comme d'autres l'ont expliqué, il est utilisé pour masquer une méthode existante. C'est utile pour remplacer une méthode qui n'est pas virtuelle dans la classe parente.

N'oubliez pas que la création d'un "nouveau" membre n'est pas polymorphe. Si vous convertissez l'objet en type de base, il n'utilisera pas le membre du type dérivé.

Si vous avez une classe de base:

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

Et puis la classe dérivée:

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

}

Si vous déclarez un type de DerivedType, puis le diffusez, la méthode DoSomething() n'est pas polymorphe, elle appellera la méthode de la classe de base, pas la méthode dérivée.

BaseClass t = new DerivedType();
t.DoSomething();// Calls the "DoSomething()" method of the base class.
21
Dan Herbert

De la docs:

Si la méthode de la classe dérivée est précédée du nouveau mot-clé, la méthode est définie comme indépendante de la méthode de la classe de base.

Qu'est-ce que cela signifie en pratique:

Si vous héritez d'une autre classe et que vous avez une méthode qui partage la même signature, vous pouvez la définir comme "nouvelle" afin qu'elle soit indépendante de la classe parente. Cela signifie que si vous avez une référence à la classe 'parent', cette implémentation sera exécutée. Si vous avez une référence à la classe enfant, cette implémentation sera exécutée.

Personnellement, j'essaie d'éviter le mot-clé "nouveau" car cela signifie normalement que ma hiérarchie de classe est fausse, mais il peut parfois être utile. Un emplacement est pour la gestion des versions et la compatibilité ascendante.

Il y a beaucoup d'informations dans le MSDN pour cela .

6
jonnii

Cela signifie que la méthode remplace une méthode du même nom hérité de la classe de base. Dans votre cas, vous n'avez probablement pas de méthode portant ce nom dans la classe de base, ce qui signifie que le nouveau mot-clé est totalement superflu.

3
Robin Clowers

Longue histoire courte - ce n'est pas obligatoire, cela change pas de comportement, et il est purement là pour la lisibilité.

C'est pourquoi dans VS, vous verrez un peu ondulé, mais votre code sera compilé et fonctionnera parfaitement et comme prévu.

On peut se demander s’il valait vraiment la peine de créer le mot-clé new alors que tout ce que cela signifie est que le développeur reconnaît "Oui, je sais que je cache une méthode de base, oui, je sais que je ne fais rien en ce qui concerne virtual ou overriden (polymorphisme ) - Je veux vraiment créer sa propre méthode ".

C'est un peu bizarre pour moi, mais peut-être uniquement parce que je viens d'un contexte Java et qu'il y a cette différence fondamentale entre C# inheritance et Java: Dans Java, les méthodes sont virtuelles par défaut, sauf si spécifié par final. Dans C#, les méthodes sont finales/concrètes par défaut, sauf si spécifié par virtual.

3
mmcrae

De MSDN :

Utilisez le modificateur new pour masquer explicitement un membre hérité d'un classe de base. Pour masquer un membre hérité, déclarez-le dans le dérivé classe utilisant le même nom et modifiez-le avec le nouveau modificateur.

1
Doug R

Faites attention à cela.
Vous avez une méthode définie dans une interface implémentée dans une classe de base. Vous créez ensuite une classe dérivée qui masque la méthode de l'interface, mais ne déclarez pas spécifiquement que la classe dérivée implémente l'interface. Si vous appelez ensuite la méthode via une référence à l'interface, la méthode de la classe de base sera appelée . Cependant, si votre classe dérivée l'implémente spécifiquement, sa méthode sera appelée quel que soit le type de référence utilisé.

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