2017-02-02 5 views
3

Je ne comprends pas pourquoi la classe SecondChildDoSomething ne sera plus appelée lorsque la classe Child sera initialisée.Pourquoi la méthode de substitution de la classe SecondChild n'est pas invoquée deux fois?

class Parent 
{ 
    public Parent() 
    { 
     DoSomething(); 
    } 
    protected virtual void DoSomething() 
    { 
     Console.WriteLine("Parent Method"); 
    } 
} 
class Child : Parent 
{ 
    private string foo; 

    public Child() 
    { 
     foo = "HELLO"; 
    } 
    protected override void DoSomething() 
    { 
     Console.WriteLine(foo.ToLower()); 
    } 
} 
class SecondChild : Parent 
{ 
    public SecondChild() 
    { 
     var c = new Child(); 
    } 

    protected override void DoSomething() 
    { 
     Console.WriteLine("In second Child"); 
    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     SecondChild c = new SecondChild(); 
     Console.ReadLine(); 
    } 
} 

Je me attendais à ce que DoSomething() de SecondChild sera appelé deux fois, mais à la place Child classe DoSomething() est invoquée qui donnera NullException.

+2

Veuillez utiliser un débogueur: Vous créez uniquement l'instance _one_ 'SecondChild'. Dans ce constructeur, vous créez une instance _'Child'_ (pas un 'SecondChild'), alors pourquoi' SecondChild.DoSomething() 'devrait être appelé deux fois? –

+1

Vous devez inclure les résultats réels et attendus à la question. Aussi, lisez http://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor, cela pourrait expliquer certaines choses – grek40

+0

Ajouter les sorties attendues et réelles. "appelé à nouveau" est trop flou. –

Répondre

4

J'ai ajusté Votre définition un peu:

class Parent 
{ 
    protected string foo; 
    public Parent() 
    { 
     foo = "Parent1"; 
     DoSomething(); 
     foo = "Parent2"; 
    } 
    protected virtual void DoSomething() 
    { 
     Console.WriteLine("Parent Method"); 
    } 
} 

class Child : Parent 
{ 

    public Child() 
    { 
     foo = "HELLO"; 
    } 
    protected override void DoSomething() 
    { 
     Console.WriteLine(foo.ToLower()); 
    } 
} 

class SecondChild : Parent 
{ 
    public SecondChild() 
    { 
     var c = new Child(); 
    } 

    protected override void DoSomething() 
    { 
     Console.WriteLine("In second Child"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     SecondChild c = new SecondChild(); 
     Console.ReadLine(); 
    } 
} 

sortie pour ce sera:

En deuxième enfant

Parent1

Raison pourquoi? Regardez l'ordre d'appel de méthode:

new SecondChild() 
    -> SecondChild:base() 
     -> base.DoSomething() //virtual 
    -> SecondChild.DoSomething() 
    -> new Child() 
    -> Child:base() 
     -> base.DoSomething() //virtual 
    -> Child.DoSomething() 
0

bien DoSomething() son déclenchée lorsqu'un créer une instance de la classe SecondChild, mais lorsque vous créez et instance de la classe des enfants, d'abord il execute le constructeur de la classe parent, qui est L'appel de la méthode DoSomething de la classe enfant est OK, mais comme le constructeur de la classe Child n'est pas encore exécuté, le champ foo ne l'est pas encore et fait foo.ToLower() renvoie une exception de référence null.

DoSomething est de s'appeler deux fois, une fois de classe des enfants et une fois pour SecondChild, mais pour la classe des enfants est jeter exception à cause de foo est nulle

Ainsi sont exécutées la partie difficile ici le constructeur de base avant que le constructeur du dérivé class