Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking constructor of derived class execute before constructor of base class

Well, originally I had a couple of constants (like MAX_SPEED) with different values in every of the derived classes. The idea was to use those values in some methods of the base class. That's when I realized that I cannot do that with constants, so I created read-only properties.

I need a method to assign those values to private fields at the moment of the instantiation, preferably in the base class. But first I have to assing the original values in derived classes. Since those are properties, I couldn't find a way to initialize them while defining, so the only way to do that is in the derived constructors.

That's where the problem comes: values are initialized after their assigning to private fields in the base class. The solution I get away with is to create a virtual method and to do assigning there.

Is there a way to call a base constructor from derived class so that the code from derived constructor will be invoked first?

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

Of course in the example it would work the other way around. Is there a solution?

like image 565
msgmaxim Avatar asked May 11 '13 15:05

msgmaxim


2 Answers

No. The base class constructor is always executed before the body of the derived class constructor. However:

  • Any instance variable initializers in the derived class are executed before the base class constructor
  • The base class constructor can execute virtual methods which can be overridden in the derived class. This is almost always a bad idea though. (All kinds of normal preconditions are invalid at this point. You can observe readonly variables which haven't been set yet because they'll be set in the constructor body, for example. Ick.)

To demonstrate both of these:

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

Output:

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

Additionally, if your base class constructor takes a parameter, then you can execute some code in the derived class in order to provide an argument:

DerivedClass() : base(SomeStaticMethod())

All of these are fairly smelly though. What's your specific situation?

like image 93
Jon Skeet Avatar answered Sep 30 '22 20:09

Jon Skeet


No, you can't do that. Base classes are always initialized first. However, you can do something like this:

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();
    }
}
like image 27
p.s.w.g Avatar answered Sep 30 '22 18:09

p.s.w.g