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:

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.

Is that appearance accurate, or misleading?

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!

Ah, yes. I should have mentioned that. The rules for static constructors and static fields are subtly different, and I do not intend this article to discuss anything about the rules for statics. That's a great topic for a follow-up article.

I suspect there is a good reason behind every 'confusing' behavior... I think I know why the following program has to behave that way but I find it confusing nevertheless.

class Program {

static void Main() {

B b = new B();

b.Display();

b.OtherDisplay();

}

}

class A {

public void Display() {

Console.WriteLine("from A");

}

}

class B : A {

new void Display() {

Console.WriteLine("from B");

}

public void OtherDisplay() {

Display();

}

}

Richard

18 Feb 2008 11:19 AM

I'll make a guess:

If it's done the 'obvious' way, there exists a point (during the base constructor) where the derived readonly field exists but is 0. There exists a later point where the same (readonly) field has a different value. That's presumably not good.

If it's done the other way around, then by the time any code runs which has access to the new object (the ObjectConstructor), all the readonly fields are fully initialized.

I'll guess further that this behaviour is due to some kind of weirdness in C# whereby the object's dynamic type is the type of the full object throughout construction, rather than the dynamic type changing as more constructors get called, as happens in C++.

Correct, though your characterization of the CLR semantics for the dynamic type of an object as "weirdness" is itself somewhat weird. I would argue that it is more weird for the dynamic type of an object to change throughout that object's lifetime! The type of an object is a constant from the moment it is created through to the moment it is destroyed. Mutable objects are hard enough to reason about; objects that mutate their own runtime type are truly odd.