为什么不会两次调用SecondChild类的重写方法?

时间:2017-02-02 09:29:49

标签: c# constructor virtual-method

我不清楚为什么在SecondChild类初始化时不会再次调用DoSomethingChild

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

我希望此处DoSomething()的{​​{1}}将被调用两次,而是调用SecondChildChild,这将提供 NullException

2 个答案:

答案 0 :(得分:4)

我稍微调整了你的定义:

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

此输出将为:

  

在第二个孩子

     

parent1

原因是什么?查看方法调用顺序:

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

答案 1 :(得分:0)

DoSomething()在创建SecondChild类的实例时调用它,但是当你创建类Child的实例时,首先它执行Parent类的构造函数,它调用子类的DoSomething方法,这是好的,但是因为Child类的构造函数还没有执行,所以foo字段还没有执行foo.ToLower()抛出空引用异常。

DoSomething被调用两次Child类和一次调用SecondChild,但是由于foo为null,因为Child类抛出异常

所以这里棘手的部分基础构造函数在派生类

的构造函数之前执行