Search code examples
c#propertiesoverridingvirtual

Why does an overridden virtual property always point to the base class's getter and setter methods of the property


A theoretical question.. I have a virtual property in a class. Another class which extends that class, even though overrides the virtual property, seems to never actually override the base property's getter or setter methods. What am I missing?

class BaseClass
{
    protected string bla;

    public virtual string Bla
    {
        get { return this.bla; }
        set { this.bla = value; }
    }

    protected BaseClass() { } 

    public BaseClass(string _bla)
    {
        this.Bla = _bla;
    }
}

class ChildClass : BaseClass
{
    private string bla2;

    public override string Bla
    {
        get
        {
            return bla2;
        }
        set
        {
            bla2 = value;
        }
    }

    public ChildClass(string _bla2) : base("AAA")
    {
        this.Bla = _bla2;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var c = new ChildClass("Me");

        Console.WriteLine(c.Bla);

        Console.ReadLine();
    }
}

I think, I got the answer.


Solution

  • If you fix up the code so that it compiles, it works as expected. However, pay attention to the comments that I added! You're calling a virtual method (a property setter, but still a method) from a constructor. That's bad.

    using System;
    
    namespace Demo
    {
        class BaseClass
        {
            protected string bla;
    
            public virtual string Bla
            {
                get
                {
                    return this.bla;
                }
                set
                {
                    this.bla = value;
                }
            }
    
            protected BaseClass()
            {
            }
    
            public BaseClass(string _bla)
            {
                this.Bla = _bla;
            }
        }
    
        class ChildClass: BaseClass
        {
            private string bla2;
    
            public override string Bla
            {
                get
                {
                    return bla2;
                }
                set
                {
                    bla2 = value;
                }
            }
    
            public ChildClass(string _bla2)
                : base("AAA")
            {
                // Step into the next line of code in the debugger.
                // You'll see that it goes into the ChildClass.Bla setter.
                // However note that this is making a virtual call in a constructor 
                // - which is very bad if there is a further derived class because
                // it will call a method in that derived class before that derived
                // class has been constructed.
                // You can fix this potential problem by making this entire class
                // sealed or by making the property sealed in this class.
    
                this.Bla = _bla2; 
            }
        }
    
        class Program
        {
            private void run()
            {
                var c = new ChildClass("X");
    
            }
    
            static void Main(string[] args)
            {
                new Program().run();
            }
        }
    }