在基类的构造函数之前调用派生类的构造函数

时间:2013-05-11 15:46:44

标签: c# inheritance constructor

好吧,最初我有几个常量(比如MAX_SPEED)在每个派生类中都有不同的值。我们的想法是在基类的某些方法中使用这些值。那时我才意识到我不能用常数做到这一点,所以我创建了只读属性。

我需要一种方法在实例化时将这些值分配给私有字段,最好是在基类中。但首先我必须在派生类中确定原始值。由于这些是属性,我在定义时找不到初始化它们的方法,因此唯一的方法是在派生构造函数中。

问题出现了:在分配给基类中的私有字段后,值被初始化。我得到的解决方案是创建一个虚拟方法并在那里进行分配。

有没有办法从派生类调用基础构造函数,以便首先调用派生构造函数中的代码?

class BaseClass
{
    public BaseClass()
    {
        System.Console.WriteLine("This should be shown after");
    }
}

class DerivedClass : BaseClass
{
    public DerivedClass() : base()
    {
        System.Console.WriteLine("This should be shown first");
    }
}

当然,在这个例子中,它可以反过来运作。有解决方案吗?

3 个答案:

答案 0 :(得分:13)

没有。基类构造函数始终在派生类构造函数的主体之前执行。但是:

  • 派生类中的任何实例变量初始值设定项都在基类构造函数
  • 之前执行
  • 基类构造函数可以执行可以在派生类中重写的虚方法。 这几乎总是一个坏主意。(此时所有类型的正常前置条件都是无效的。您可以观察尚未设置的只读变量,因为它们将在构造函数体中设置,例如.Ick。)

要证明这两点:

using System;

class BaseClass
{
    public BaseClass()
    {
        VirtualMethod();
        Console.WriteLine("BaseClass ctor body");
    }

    public virtual void VirtualMethod()
    {
        Console.WriteLine("BaseClass.VirtualMethod");
    }
}

class DerivedClass : BaseClass
{
    int ignored = ExecuteSomeCode();

    public DerivedClass() : base()
    {
        Console.WriteLine("DerivedClass ctor body");
    }

    static int ExecuteSomeCode()
    {
        Console.WriteLine("Method called from initializer");
        return 5;
    }

    public override void VirtualMethod()
    {
        Console.WriteLine("DerivedClass.VirtualMethod");
    }
}

class Test
{
    static void Main()
    {
        new DerivedClass();
    }
}

输出:

Method called from initializer
DerivedClass.VirtualMethod
BaseClass ctor body
DerivedClass ctor body

此外,如果您的基类构造函数接受一个参数,那么您可以在派生类中执行一些代码以提供参数:

DerivedClass() : base(SomeStaticMethod())

所有这些都是相当臭的。你的具体情况是什么?

答案 1 :(得分:8)

不,你不能这样做。基类始终首先初始化。但是,您可以这样做:

class BaseClass
{
    public BaseClass()
    {
        this.Initialize();
    }

    protected virtual void Initialize()
    {
        System.Console.WriteLine("This should be shown after");
    }
}

class DerivedClass : BaseClass
{
    public DerivedClass() : base()
    {
    }

    protected override void Initialize()
    {
        System.Console.WriteLine("This should be shown first");
        base.Initialize();
    }
}

答案 2 :(得分:0)

还有一个选项是将子类构造函数设置为static,以便它首先执行父类构造函数。但它不会违反oop设计