2009-09-24 4 views
1

Est-ce correct d'utiliser le mot-clé new à un moment donné pour remplacer le type de retour dans une méthode? Puis-je utiliser virtual new ou new virtual pour pouvoir remplacer le type de retour?Opérateurs nouveaux et virtuels en C#

Je dois aussi considérer les classes qui héritent de ce point. Peuvent-ils remplacer cette méthode où la base a été créée avec new?

Répondre

14

Vous pouvez cela, mais la vraie question est de savoir si vous devez faire.

Le problème est que vous aurez un comportement très inattendu, selon la façon dont votre classe est utilisée. Si vous appelez votre classe à partir d'une instance de la classe de base, la méthode originale, non "nouvelle", sera appelée, ce qui sera probablement inattendu. En général, j'éviterais d'utiliser le nouveau mot-clé pour surcharger une méthode de classe de base, sauf s'il y a une raison très distincte de le faire - si votre méthode retourne un nouveau type, déclarez-la comme une nouvelle méthode avec un nom ou une signature différent au lieu de cacher la méthode de la classe de base - cela rendra votre hiérarchie beaucoup plus utilisable.

+1

Je suis entièrement d'accord. Vous devriez avoir une raison très convaincante de le faire. Une relation d'héritage est une relation "IS A", donc si A hérite de B, alors A est un B. Cela signifie que A devrait aussi se comporter comme s'il s'agissait d'un B. – Pete

+0

Je suis entièrement d'accord avec vous. La raison pour laquelle je le fais est parce que je travaille avec du code hérité :(. Il a été fait de cette façon et je peux le changer.Je n'aime pas non plus mais je l'ai aussi.La seule chose dont je suis sûr maintenant que tous les endroits où les nouvelles classes seront utilisées seront appelés au moins à partir du niveau où le "nouveau" a été déclaré – jmayor

+0

Comme je l'ai dit, vous pouvez le faire - personnellement, je vous recommande de changer le nom de la méthode, juste pour éviter ce cas, cependant, cela rend la vie très confuse. –

0

Hypothétiquement ....

public class BaseCollection<T> 
{ 
    // void return - doesn't seem to care about notifying the 
    // client where the item was added; it has an IndexOf method 
    // the caller can use if wants that information 
    public virtual void Add(T item) 
    { 
    // adds the item somewhere, doesn't say where 
    } 

    public int IndexOf(T item) 
    { 
    // tells where the item is 
    } 
} 

public class List<T> : BaseCollection<T> 
{ 
    // here we have an Int32 return because our List is friendly 
    // and will tell the caller where the item was added 
    new public virtual int Add(T item) // <-- clearly not an override 
    { 
    base.Add(item); 
    return base.IndexOf(item); 
    } 
} 

Ici, j'utiliser le modificateur "nouveau", car une liste <T> référence cachera la méthode Add de la BaseCollection <T>. Par défaut, le fait de masquer les membres d'une base génère un avertissement du compilateur (une erreur si la compilation est configurée pour échouer sur les avertissements). Donc je dis en gros au compilateur ... "Ouais, je sais que j'ai caché la méthode Add avec le retour vide, c'est la fonctionnalité désirée - allez-y."

Questions connexes