This program throws an exception at runtime. If you've been burned by this problem before, you'll know what's wrong before you even see the definition for class Bar...
using System;
class Program
{
static void Main()
{
Foo foo = new Bar();
}
}
abstract class Foo
{
public Foo()
{
Init();
}
protected abstract void Init();
}
class Bar : Foo
{
string message;
public Bar()
{
message = "Hello!";
}
protected override void Init()
{
Console.WriteLine(message.ToUpper());
}
}
Comments
Because the base class constructor executes before the child class constructor.
i'm guessing the Foo constructor runs before the Bar constructor so you will get a nullreferenceexception when ToUpper() is called on the string.
For instance, as soon as Bar() is called, the consructor for Foo is called which in turn calls Bar's Init() and only after all this is message set to "Hello!". Is my thinking correct here?
This should result in a Null Pointer exception I asume.
--
Lars Wilhelmsen
In this particular case, when Bar gets created, it calls the base (Foo) class constructor before doing anything else.
Foo calls Init() in its constructor, which is abstract. This means that Bar.Init() gets called.
Here, you'll be greeted by a nice "null ref exception" :)
BTW: if you wanted to be more evil, you could have defined Foo.Init() as virtual and give it a body. The result would have been the same, but it would have been harder to spot.
Init is called before the Bar constructor has run so message will be null.
That's why FxCop tells me I'm a bad boy when I do this kind of thing
When the constructor of the Bar class is called, it calls base class (Foo) constructor first, before executing message = "Hello!"; line. The Foo class constructor calls Init() method. This method tries to write the uppercase message, but fails because the message is null. ToUpper() (or any other instance method call) cannot be called on a null string.
First thing a Ctor is doing is called it's base class Ctor. Thus Bar Ctor is called first and then its calling Init() which will result in object null reference exception since message was not initialize yet.
There's an FxCop rule to warn you about this problem, I believe.
@ChrisM: Foo's ctor will always be called when I create a Bar (irregardless of my variable type).
To everyone who mentioned "virtual method calls from a constructor" - that is the crux of the problem. The virtual method will execute in the most derived class that overrides the method - and will do so before the ctor of the most derived class executes. Yes, there is an FxCop rule to catch this evil practice.
But if it's impossible to avoid this situation, why is virtual calls even possible from the constructor?
So my answer is: there should be a compiler error at the constructor in Foo because it's an abstract class but there's code in it. Abstract classes should only have abstract methods on them, remember.
I think you both propose that the compiler should prevent this problem. It's such a well known problem that they must have a convincing argument to let it pass.