I was reviewing some code today and came across some code (accurately portrayed by this snippet)…
public abstract class FlargBase{
public FlargBase(){
this.DoSomething();
}
public abstract void DoSomething();
}
public class PurpleFlarg: FlargBase{
public PurpleFlarg()
: base(){
}
public override void DoSomething(){
// Do something here;
}
}
The compiler gives no errors or warnings, but CodeAnalysis warns that the call chain contains a call to a virtual method and may produce unintended results.
I was curious because, as I see it, two things can happen.
Creating an instance of the base class will make a call to a method with no defined implementation. I would expect the compiler to error, or the runtime to throw an exception due to a missing implementation. I’m assuming the compiler is providing an implementation of {}I mis-typed the original code; it did contain the abstract keyword on the class.- Creating an instance of a derived class will cause a call to a method on a class that has not actually been constructed yet. I would have expected this to throw an exception.
This code has been in a production environment for several months. It is apparently working correctly enough that no one has noticed any strange behavior.
I’m hoping the incredible talent here at StackOverflow can give me some insight into the behavior and consequences of this code.
A C# object is fully constructed and initialized to zero before the first constructor runs. The base constructor will call the derived implementation of the virtual method.
It’s considered bad style to do this, because the derived implementation might behave strangely when the constructor of the derived class has not been called yet. But the behavior by itself is well defined. If you do nothing in the derived implementation that requires the code from the constructor to have already run, it will work.
You can image that the runtime calls the most derived constructor first. And its first action is to implicitly call the base constructor. I’m not sure if it’s actually implemented like that, but since some .net languages allow you to call the base constructor at an arbitrary point of the derived constructor, I expect C# to simply call the base class constructor as first action of the derived constructor.
This behavior is very different from how C++ handles it. In C++ the derived classes get constructed one after the other, and before the constructor of the derived class has started the object has still the type of the baseclass and the overrides from the derived class are ignored.