0

I have the following scenario:

Class A
{
    public static  A instance;

    static A()
    {
        if(condition)
        {
            instance = new B();
        }
        else
        {
            instance = new A();
        }

    }

    public A()
    {
        WriteSomething();
    }

    virtual void WriteSomething()
    {
        Console.WriteLine("A constructor called");
    }

}


Class B : A
{
    public B()
    {
        WriteSomething();
    }

    override void WriteSomething()
    {
        Console.WriteLine("B constructor called");
    }

}

The problem is that when A.instance is called the first time and if condition is true and the B() constructor is called, for some reasons I do not undestand the output of the program is "A constructor called".

Can you please help with an explanation!

Thank you!

4
  • 2
    Calling virtual function in the constructor may be the problem. Why not try writing output in a separate virtual function? Commented May 9, 2014 at 15:31
  • 2
    What is setting the condition value? Could you also put the calling code into the question so that we can see everything you're doing? Commented May 9, 2014 at 15:32
  • This is a stripped down version of a very big legacy code, and it's just for exemplification. The reale code does a lot of things in the virtual method, and cannot be moved somewhere else. Commented May 9, 2014 at 15:33
  • @MattJones The condition is read from a enviroment variable. The calling code just calls A.instance. Commented May 9, 2014 at 15:34

2 Answers 2

1

The constructor for A will always run first, even if you are creating a new B, since B extends A.

You have also inadvertently discovered why it's recommended that you don't put virtual function calls in a constructor (at least in .NET).

http://msdn.microsoft.com/en-us/library/ms182331.aspx

"When a virtual method is called, the actual type that executes the method is not selected until run time. When a constructor calls a virtual method, it is possible that the constructor for the instance that invokes the method has not executed."

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! I forggot about this default OOP behaviour.
0

A.WriteSomething() will always give you "A constructor called" B.WriteSomething() will always give you will always give you "A constructor called". However in a constructor scenario, override is not being called, you can use new keyword to make new voids with the same name. This works the way you want besides a virtual override call. However, the code above is not a good implementation.

Class A
{
    public static  A instance;

    static A()
    {
        if(condition)
        {
            instance = new B();
        }
        else
        {
            instance = new A();
        }

    }

    public A()
    {
        WriteSomething();
    }

    public static void WriteSomething()
    {
        Console.WriteLine("A constructor called");
    }

}


Class B : A
{
    public B()
    {
        WriteSomething();
    }

    public static new void WriteSomething()
    {
        Console.WriteLine("B constructor called");
    }

}

3 Comments

You've completely changed the public interface of his classes here. And the new keyword, in the sense used here, is a really bad idea that busts polymorphism.
@BrucePierson I agree, the code itself should be re-written. He was calling a virtual method in the constructor which doesn't make sense. I just wanted to give an example what can be done.
Fair enough, but please don't encourage the use of new - it's one of MS's worst ideas.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.