2010-09-05 4 views
9
class Base 
{ 
    public virtual void MethodA(int x) 
    { 
     Console.WriteLine ("In Base Class"); 
    } 
} 

class Derived : Base 
{ 
    public override void MethodA(int x) 
    { 
     Console.WriteLine ("In derived INT)"); 
    } 

    public void MethodA(object o) 
    { 
     Console.WriteLine ("In derived OBJECT"); 
    } 
} 

class Test 
{ 
    static void Main() 
    { 
     Derived d = new Derived(); 
     int k = 20; 
     d.MethodA(k); 
    } 
} 

La sortie que j'ai eu pour ceci est "In OBJECT dérivé". Quelle est la raison de ce comportement étrange? Après quelques recherches, j'ai découvert que la raison est les signatures déclarées dans la classe de base sont ignorées. Pourquoi sont-ils ignorés?Pourquoi les signatures déclarées dans la classe de base sont-elles ignorées?

+1

+1 à la question, je suis d'accord ce comportement contre-intuitif. –

+0

Je suis d'accord que le comportement est étrange. Je voudrais savoir: demandez-vous cela parce que vous voulez vraiment faire cela ou parce que vous étiez curieux? Je ne vois pas de raison d'implémenter quelque chose comme ça, mais j'aimerais bien savoir pourquoi cela arrive. –

+0

duplication possible de [Comment la méthode de masquage fonctionne en C#? (Deuxième partie)] (http://stackoverflow.com/questions/710459/how-method-hiding-works-in-c-part-two) –

Répondre

6

Ceci est par nature et pour une bonne raison. Cette conception permet d'éviter le problème de la classe de base fragile. C# a été conçu pour rendre plus facile et plus sûr d'écrire des composants «versionnés», et cette règle en est une grande partie.

Ceci est une question très fréquemment posée. C'est l'un des "rapports de fausses alertes" les plus communs que nous obtenons; c'est-à-dire que quelqu'un croit avoir trouvé un bogue dans le compilateur alors qu'en fait il a trouvé une fonctionnalité.

Pour une description de la fonction et la raison pour laquelle il est conçu comme ça, voir mon article sur le sujet:

http://blogs.msdn.com/b/ericlippert/archive/2007/09/04/future-breaking-changes-part-three.aspx

Pour plus d'articles sur le sujet de la façon dont les différentes langues face à la Brittle problème de classe de base voir mes archives d'articles sur le sujet:

http://blogs.msdn.com/b/ericlippert/archive/tags/brittle+base+classes/

2

Le compilateur dans VC# 2008 vérifie les fonctions non virtuelles disponibles avant les fonctions virtuelles, au moment de décider quoi appeler. Puisque votre classe Dérivée a un MethodA (objet) non virtuel qui peut être appelé, le compilateur l'appelle.

Si vous ajoutez un MethodA virtuel (objet) à Base, alors Derived.MethodA (int) sera appelé, car alors MethodA (objet) et MethodA (int) sont des virtual.

Je ne connais pas suffisamment la spécification de langage C# pour savoir s'il s'agit d'un comportement spécifié ou d'un bogue dans le compilateur.

+0

Il est en effet dans la spécification ECMA, non-virtuelle sera invoquée en premier. Notez également que la méthode appelée est déterminée par le compilateur pour les méthodes non virtuelles et par le type d'exécution pour les méthodes virtuelles. –

+0

J'ai vérifié ceci, mais méfiez-vous que Derived.MethodA (int) ne sera appelé que lorsque vous ajouterez le mot-clé 'override' à Derived.MethodA (objet) (c'était bien entendu). Sans cela, le mot-clé optionnel 'nouveau' est supposé et Derived.MethodA (objet) sera toujours appelé. – Gerard

Questions connexes