6

Today I came up with an interesting problem. I noticed that the following code:

class A
{
    public A()
    {
        Print();
    }
    public virtual void Print()
    {
        Console.WriteLine("Print in A");
    }
}

class B : A
{
    public B()
    {
        Print();
    }

    public override void Print()
    {
        Console.WriteLine("Print in B");
    }
}

class Program
{
    static void Main(string[] args)
    {
        A a = new B();
    }
}

Prints

Print in B
Print in B

I want to know why does it print the "Print in B" twice.

Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
NarbehM
  • 345
  • 2
  • 13

5 Answers5

11

I want to know why does it print the "Print in B" twice.

You're calling a virtual method twice, on the same object. The object is an instance of B even during A's constructor, and so the overridden method will be called. (I believe that in C++, the object only "becomes" an instance of the subclass after the base class constructor has executed, as far as polymorphism is concerned.)

Note that this means that overridden methods called from a constructor will be executed before the derived class's constructor body has had a chance to execute. This is dangerous. You should almost never call abstract or virtual methods from a constructor, for precisely this reason.

EDIT: Note that when you don't provide another constructor call to "chain" to using either : this(...) or : base(...) in the constructor declaration, it's equivalent to using : base(). So B's constructor is equivalent to:

public B() : base()
{
    Print();
}

For more on constructor chaining, see my article on the topic.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
2

Unlike C++ where calls of virtuals in the constructor are restricted to the definition within the class itself, the overrides are fully honored in C#'s constructors. The practice is frowned upon, and for a good reason (link), but it is still allowed: A's constructor calls the override supplied by B, producing the output that you see. This is the normal behavior of overriden virtual functions.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

Because B override's the Print method. Your variable a is of type B, and B's Print method looks like this:

public override void Print()
{
    Console.WriteLine("Print in B");
}
Dave Zych
  • 21,581
  • 7
  • 51
  • 66
2

If you do not call a base class constructor, the default constructor for the base class will be called implicitly (MSDN).

You would not get the double output if you defined your class A constructors this way:

class A
{
    public A()
    {
        // does nothing
    }

    public A(object a)
    {
        Print();
    }
}

The reason it prints "Print in B" both times is that Print() is overridden in the class B so B.Print() is what is called by both constructors.

I think you can force the A.Print() to be called in the A constructor as follows:

class A
{
    public A()
    {
        ((A)this).Print();
    }
}

Hope this helps.

saarp
  • 1,931
  • 1
  • 15
  • 28
1

Because you have an instance of B which overrides Print, so that overridden method gets called. Also, A's ctor will run, followed by B's which is why it gets printed twice.

Andy
  • 8,432
  • 6
  • 38
  • 76