Search code examples
c#automatic-properties

Why does an overridden get-only property stay null when set in base class constructor?


I tried the following example:

public class TestBase
{
    public virtual string ReadOnly { get; }

    public TestBase()
    {
        ReadOnly = "from base";
    }
}

class Test : TestBase
{
    public override string ReadOnly { get; }
    public Test()
    {
        // nothing here
    }
}

When I create an instance of Test, I see that ReadOnly stays null. But why? I really do not get the hang of it, could somebody please explain to me why this happens? At least I would expect an error, that a read-only property cannot be set outside of the owning class.


Solution

  • The compiler treats this as below; basically, the code in the constructor writes to the original backing field, in TestBase. It seems that yours is not a supported scenario, but... I do wonder whether the language team have considered this case.

    BTW: if you ever want to see what the compiler does with code: sharplab.io

    public class TestBase
    {
        [CompilerGenerated]
        private readonly string <ReadOnly>k__BackingField; // note: not legal in "real" C#
    
        public virtual string ReadOnly
        {
            [CompilerGenerated]
            get
            {
                return <ReadOnly>k__BackingField; // the one in TestBase
            }
        }
    
        public TestBase()
        {
            <ReadOnly>k__BackingField = "from base";
        }
    }
    internal class Test : TestBase
    {
        [CompilerGenerated]
        private readonly string <ReadOnly>k__BackingField;
    
        public override string ReadOnly
        {
            [CompilerGenerated]
            get
            {
                return <ReadOnly>k__BackingField; // the one in Test
            }
        }
    }