2017-02-02 3 views
3

Ich bin nicht klar darüber, warum die SecondChild Klasse DoSomething nicht erneut aufgerufen wird, wenn Child Klasse initialisiert wird.Warum überschreiben Methode der SecondChild-Klasse wird nicht zweimal aufgerufen?

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(); 
    } 
} 

Ich hatte erwartet, dass DoSomething() von SecondChild zweimal hier genannt werden, sondern Child Klasse DoSomething() aufgerufen, dieNullException geben wird.

+2

Bitte verwenden Sie einen Debugger: Sie erstellen nur _one_ 'SecondChild' Instanz. In diesem Konstruktor erstellen Sie eine _'Child'_ -Instanz (kein 'SecondChild'). Warum sollte also' SecondChild.DoSomething() 'zweimal aufgerufen werden? –

+1

Sie sollten die tatsächliche und die erwartete Ausgabe der Frage hinzufügen. Lesen Sie auch http://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor, es könnte einige Dinge erklären – grek40

+0

Fügen Sie erwartete und tatsächliche Ausgaben hinzu. "Wieder angerufen" ist zu unscharf. –

Antwort

4

Ich habe Deine Definition ein wenig angepasst:

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(); 
    } 
} 

Ausgang hierfür wird sein:

Im zweiten Kind

parent1

Grund, warum? Schauen Sie sich den Methodenaufruf Bestellung:

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

Well DoSomething() seine, wenn aufgerufen eine Instanz von SecondChild Klasse, aber wenn Sie erstellen und Instanz der Klasse Kind, es zuerst den Konstruktor der Eltern-Klasse ausführen, das ist Aufrufen der DoSomething-Methode der untergeordneten Klasse, die OK ist, aber weil der Konstruktor der Child-Klasse noch nicht ausgeführt wird, ist das foo-Feld noch nicht vorhanden, und foo.ToLower() löst eine Nullreferenzausnahme aus.

DoSomething wird immer zweimal einmal der Kinderklasse und einmal für SecondChild, aber für Kinder Klasse wirft Ausnahme wegen foo ist null genannt

So ist der schwierige Teil hier die Basiskonstruktor vor dem Konstruktor der abgeleiteten ausgeführt werden sollen Klasse

Verwandte Themen