Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we need to explicitly call parent constructor in MSIL?

I just spent hours being confused by an NullReferenceException where I thought there shouldn't be one. I was constructing a class like so:

public class MyClass : MyBase<Foo>
{
    public MyClass()
    {
        base.Method(Foo.StaticField);
    }
}

where

public class MyBase<T>
{
    private SomeObject bar = new SomeObject();

    public void Method(object o)
    {
        this.bar.AnotherMethod(o); // exception thrown here
    }
}

Basically my IL was the following:

ctorIl.Emit(OpCodes.Ldarg_0);
ctorIl.Emit(OpCodes.Ldsfld, staticField);
ctorIl.Emit(OpCodes.Box, typeof(FieldType));
ctorIl.Emit(OpCodes.Call, parentMethod);
ctorIl.Emit(OpCodes.Ret);

and I finally figured that it must be that bar was not being instantiated. I constructed my class in C# and compiled it and found the only difference was that the following should be above the IL above:

ctorIl.Emit(OpCodes.Ldarg_0);
ctorIl.Emit(OpCodes.Call, parentCtor);
// as above

With these lines, my code now works as expected.

So my questions are:

  1. Why do we need to explicitly call the base constructor to instantiate fields?
  2. Is there a legitimate use of not calling the base constructor?
  3. ...and if not, why does the CLR accept it as a valid program?
like image 454
dav_i Avatar asked Sep 11 '14 13:09

dav_i


People also ask

How can we call a parent class constructor?

For calling the constructor of a parent class we can use the super keyword. The super() method from the constructor method is used for the invocation of the constructor method of the parent class to get access to the parent's properties and methods.

Is constructor of parent class called automatically?

Note: In Java, constructor of the base class with no argument gets automatically called in the derived class constructor.

Can a child call a parent constructor?

If parent class implements a constructor with arguments and has no a constructor with no arguments, then the child constructors must explicitly call a parents constructor.

Which constructor executes first the parent constructor or the child constructor?

In simple words, we can say that the parent constructor gets called first, then of the child class.


1 Answers

  1. because it isn't automatic, and it allows compilers and IL code to decide both when and if to call the base constructor
  2. well, you can actually instantiate types without using any constructors whatsoever... edge case, sure; but allowed
  3. because it is allowed

Note that you can actually emit a simple constructor (including base call) in a single method:

typeBuilder.DefineDefaultConstructor();
like image 88
Marc Gravell Avatar answered Sep 28 '22 06:09

Marc Gravell