Why Do Initializers Run In The Opposite Order As Constructors? Part One

Why Do Initializers Run In The Opposite Order As Constructors? Part One

Rate This
  • Comments 36

Pop quiz!

What do you expect the output of this program to be?

 

using System;

class Foo
{
    public Foo(string s)
    {
        Console.WriteLine("Foo constructor: {0}", s);
    }
    public void Bar() { }
}
class Base
{
    readonly Foo baseFoo = new Foo("Base initializer");
    public Base()
    {
        Console.WriteLine("Base constructor");
    }
}
class Derived : Base
{
    readonly Foo derivedFoo = new Foo("Derived initializer");
    public Derived()
    {
        Console.WriteLine("Derived constructor");
    }
}
static class Program
{
    static void Main()
    {
        new Derived();
    }
}

I got a question from a user recently noting that the order was not as he expected. One naively expects that the order will go "base initializers, base constructor body, derived initializers, derived constructor body". In fact the order actually is that first all the initializers run in order from derived to base, and then all the constructor bodies run in order from base to derived.

The latter bit makes perfect sense; the more derived constructors may rely upon state initialized by the less derived constructors, so the constructors should run in order from base to derived. But most people assume that the call sequence of the code above is equivalent to this pseudocode:

// Expected
BaseConstructor()
{
    ObjectConstructor();
    baseFoo = new Foo("Base initializer");
    Console.WriteLine("Base constructor");
}
DerivedConstructor()
{
    BaseConstructor();
    derivedFoo = new Foo("Derived initializer");
    Console.WriteLine("Derived constructor");
}

When in point of fact it is equivalent to this:

 // Actual
BaseConstructor()
{
    baseFoo = new Foo("Base initializer");
    ObjectConstructor();
    Console.WriteLine("Base constructor");
}
DerivedConstructor()
{
     derivedFoo = new Foo("Derived initializer");
    BaseConstructor();
    Console.WriteLine("Derived constructor");
}

That explains the mechanism whereby the initializers run in order from derived to base and the constructor bodies run in the opposite order, but why did we choose to implement that mechanism instead of the more intuitively obvious former way?

Puzzle that one over for a bit, and then read on for a hint.

...

...

...

The "readonly" modifiers in there were no accident. The code gives the appearance that any call to derivedFoo.Bar() and baseFoo.Bar() should never fail with a null dereference exception because both are readonly fields initialized to non-null values.

  1. Is that appearance accurate, or misleading?
  2. Now suppose initializers ran in the "expected" order and answer question (1) again. 

I'll post the answers and analysis next week. Have a fabulous weekend!

 

  • This is why i always initialize variables in the constructor. That way u dont have to

    worry about it.

  • Consider this program which attempts to mutate a readonly mutable struct. What happens? struct Mutable

  • Exactly as Bill Sanders said. This init order is to support a polymorhic method call in the constructor.

  • it always that initializers run first- this is a key point

  • It is actually very sound to run initializes first from derived to base while constructors from base to derived. The basic purpose of the constructor is to assign some values to the member fields. Right? Now to assign the member fields the runtime must first be able to see what are those member fields? Now just have a look at the initalizer. What is an initializer? Very simply it is a statement assigning a value upon declaration.

    Now when an object is create for a particular class the fields of the class should be first declared correctly. Then it’s base class and then base of that base class until we reach system. Object. This is like constructing a building where engineers create the outer most walls of the structure first which in this case will be the fields of the outer most class. And then the support pillars inside the building. Now think of constructors as creating floors in the building. You create first floor that is the system. Object’s constructor, then you create the first floor (next class after system. object) and then you create the next till you get to last class which is the class whose object is being initialized.

  • It is actually very sound to run initializes first from derived to base while constructors from base to derived. The basic purpose of the constructor is to assign some values to the member fields. Right? Now to assign the member fields the runtime must first be able to see what are those member fields? Now just have a look at the initalizer. What is an initializer? Very simply it is a statement assigning a value upon declaration.

    Now when an object is create for a particular class the fields of the class should be first declared correctly. Then it’s base class and then base of that base class until we reach system. Object. This is like constructing a building where engineers create the outer most walls of the structure first which in this case will be the fields of the outer most class. And then the support pillars inside the building. Now think of constructors as creating floors in the building. You create first floor that is the system. Object’s constructor, then you create the first floor (next class after system. object) and then you create the next till you get to last class which is the class whose object is being initialized.

Page 3 of 3 (36 items) 123