Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 807
apfelstrudel24 Avatar asked Nov 30 '18 10:11

apfelstrudel24


People also ask

Can we override base class constructor?

Constructor looks like method but it is not. It does not have a return type and its name is same as the class name. But, a constructor cannot be overridden.

Is defined as a property in class but is overridden here in?

The error "'X' is defined as a property in class 'Y', but is overridden here in 'Z' as an accessor" occurs when a property overrides an accessor or vice versa in a derived class. To solve the error, use properties or accessors in both classes for the members you need to override.

Can we override a property in C#?

In C# 8.0 and earlier, the return types of an override method and the overridden base method must be the same. You cannot override a non-virtual or static method. The overridden base method must be virtual , abstract , or override . An override declaration cannot change the accessibility of the virtual method.


1 Answers

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         }     } } 
like image 52
Marc Gravell Avatar answered Oct 20 '22 04:10

Marc Gravell