Overriding and calling same method in Base class constructor in C#
.net, asp.net, c#, c#-4.0
Solution
What I feel is, constructor of A gets executed first when creating object of B.
Correct.
In that case, the method in B would not be hit right?
This is incorrect.
In similar code in C++ you would be correct. In C++ there is a rule that virtual function dispatch tables are built as the object is being constructed. That is, when the "A" constructor is entered, the vtable is filled in with the methods in "A". When control goes to the "B" ctor, the vtable is then filled in with the methods of B.
This is not the case in C#. In C# the vtable is filled in the moment the object comes out of the memory allocator, before either ctor is executed, and it does not change after that. The vtable slot for the method always contains the most derived method.
Therefore calling a virtual method in a ctor as you are doing here is a very bad idea. A virtual method can be called where the implementation is on a class whose ctor has not run yet! It might therefore depend on state that has not yet been initialized.
Note that field initializers run before all ctor bodies, so fortunately an override on a more derived class will always run after the field initializers of the overriding class.
The moral of the story is: simply don't do that. Don't ever call a virtual method in a ctor. In C++ you might get a different method than you expect, and in C# you might get a method that uses state that is not initialized. Avoid, avoid, avoid.
Why we shouldn't call virtual methods inside ctor? Is it because we get only the (latest derived) results only) always in the vtable?
Yes. Let me illustrate with an example:
class Bravo
{
public virtual void M()
{
Console.WriteLine("Bravo!");
}
public Bravo()
{
M(); // Dangerous!
}
}
class Delta : Bravo:
{
DateTime creation;
public override void M()
{
Console.WriteLine(creation);
}
public Delta()
{
creation = DateTime.Now;
}
}
OK, so the expected behavior of this program is that when `M` is called on any `Delta`, it will print out the time that the instance was created. But the order of events on `new Delta()` is:
- `Bravo` ctor runs
- `Bravo` ctor calls `this.M`
- `M` is virtual and `this` is of runtime type `Delta` so `Delta.M` runs
- `Delta.M` prints out the uninitialized field, which is set to the default time, not the current time.
- `M` returns
- `Bravo` ctor returns
- `Delta` ctor sets the field
Now do you see what I mean when I say that the overriding method might rely on state that is not initialized yet? In any other usage of `M`, this would be fine because the `Delta` ctor would already be finished. But here `M` is called before the `Delta` ctor even starts!
Problem
My fret is: In the code presented below, it should display `A` then `B`. But it displays `B` then `B`. Why is it so? What I feel is, constructor of `A` gets executed first when creating object of `B`. In that case, the method in `B` would not be hitted right? So it should be `A.Display()` and should result `A`. Also, then `a.Display()` should return `B` because we have override. So I expect `A` then `B`. Because its not overloading but overriding. I know the definition of these things, I expect to understand the reason for this behavior and how it works internally as I am not convinced with `BB` but `AB`. Code ``` class A { public A() { this.Display(); } public virtual void Display() { Console.WriteLine("A"); } } class B :A { public override void Display() { Console.WriteLine("B"); } } class C { static void Main() { A a = new B(); a.Display(); Console.WriteLine(); Console.ReadLine(); } } ``` Outputs 1) On override of `Display` method in the derived class yields the following: ``` A a = new A(); // ---> AA B a = new B(); // ---> BB // I expect AB. A a = new B(); // ---> BB // I expect AB. ``` 2) using the NEW keyword in the `Display` method in derived class yields the following: ``` B a = new B(); // ---> AB // I Expect AA here. A a = new B(); // ---> AA A a = new A(); // ---> AA ``` 3) More interesting findings are: When I use `base.Display()` in the derived constructor with override of the base method in derived class, it gives me `BAB` I do not see any logic at least in this. because, it should give `BBB`