Yanshof
Yanshof

Reputation: 9926

Call abstract method from class constructor

I have base class that contain abstract method.

public abstract class ClassBase : IClassBase
{
    protected ClassBase()
    {
        ////   some code 
    }

    protected ClassBase(XmlNode settings)
          : this()
    {

    }

    protected abstract void Init(XmlNode settings);
}


public class Class_A : ClassBase
{
    public Class_A(XmlNode settings)
          : this(settings)
    {
        Init(settings);
    }

    protected override void Init(XmlNode settings)
    {


    }
}

Is it ok to call the Init method from Class_A constructor ?

I try to do it and its run ok - but when the constructor is running the virtual tables are not ready yet and the abstract method are not ready as far as i know.

Upvotes: 1

Views: 4294

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1502616

It's unclear exactly what code you meant, as the code you've given doesn't compile for a couple of reasons. Most importantly, did you actually mean to call Init from ClassBase rather than from Class_A? If not, it seems pointless making Init abstract. This answer assumes you did meant that.

Is it ok to call the Init method from Class_A constructor ?

It's valid - but it's not usually a good idea.

It's not a matter of the "virtual tables" no being created - that's fine, and it will execute Class_A.Init. An object is created as an instance of its eventual type immediately. The problem is that you're calling a method on the Class_A instance before its constructor has had a chance to execute. That means it may be in an unexpected state - normal preconditions may not hold, for example.

Example

public class Class_A : ClassBase
{
    private readonly string text;

    public Class_A(XmlNode settings, string text)
        : base(settings) // Which calls Init(settings) as per intro paragraph
    { 
        if (text == null)
        {
            throw new ArgumentNullException("text");
        }
        this.text = text;           
    }

    protected override void Init(XmlNode settings)
    {
        // In here, text is still null... even though it can't be in any
        // other method.
    }
}

Just occasionally, it's the least worst solution, but in that case:

  • Really make sure there isn't a better solution
  • Document it very clearly
  • Avoid calling the method from anywhere else, as it's often odd to code an implementation which is appropriate in both "I'm half way through initialization" and "I'm fully initialized" states.

Upvotes: 6

Related Questions