Change BaseClass property to readonly in DerivedClass with new and override

▼魔方 西西 提交于 2021-01-29 04:49:54

问题


I have a situation where I want to make normal property to be readonly in derived class with default value. I am using keyword new for that purpose in the following way:

public abstract class BaseClass
{
    public virtual string SomeInfo { get; set; }
}
public class DerivedClass1 : BaseClass
{
    public new string SomeInfo => "ChildInfo1"; // C# 6.0 equivalent of { get { return "ChildInfo1"; } }
}

It works fine, and new DerivedClass1().SomeInfo cannot be assigned to -- it is readonly. I'm aware that one could access it through base class:

BaseClass b1 = new DerivedClass1();
b1.SomeInfo = "ChildInfo1 changed";

I just want to unable user to change it accidentally, and through base class it would be on purpose in which case it's acceptible.

However if Derived class would be like this:

public class DerivedClass2 : BaseClass
{
    public override string SomeInfo => "ChildInfo2";
}

Then this property would be accessible and you could seemingly change it but it would not be changed, and I would like to understand why?

var d2 = new DerivedClass2();
d2.SomeInfo = "ChildInfo2 changed";
Console.WriteLine(d2.SomeInfo); // output: ChildInfo2

UPDATE:
I have added new answer as third option, probably the best.


回答1:


In your base Class you have

public virtual string SomeInfo { get; set; }

It's just a nice definition of:

private string _someInfo;
public string SomeInfo
{
  get {return _someInfo;}
  set {_someInfo = value;}
}

if you override it with an Expression-Bodied property you override the get property with

public string SomeInfo
{
  get {return "ChildInfo2";}
}

But you don't override set property, so you could still set the private variable, but it doesn' change anything else.

if you look on your first example:

BaseClass b1 = new DerivedClass1();
b1.SomeInfo = "ChildInfo1 changed";

it happens exact the same thing, you could set property, because base class does have setter and sets a private variable, but if you try to output value of SomeProperty, you see, that it is not changed and is still "ChildInfo1"




回答2:


I have now made third options that could be the best, setting default value in Constructor. Thanks to @MatthewWatson for drawing attention to LSP and @MaksimSimkin for explanation.

public abstract class BaseClass
{
    public string SomeInfo { get; set; }
}

public class DerivedClass1 : BaseClass
{
    public DerivedClass1()
    {
        base.SomeInfo = "ChildInfo1";
    }
    public new string SomeInfo => base.SomeInfo;
}

This makes SomeInfo readOnly when accessed from DerivedClass, and if accessed through BaseClass it is editable and change regularly applies, and is visible from both classes. So there is no 'unknown' behavior.

PS For older versions of C# this is equivalent:

public abstract class BaseClass
{
    protected string _someInfo;
    public string SomeInfo
    {
        get { return _someInfo; }
        set { _someInfo = value; }
    }
}

public class DerivedClass1 : BaseClass
{
    public DerivedClass1()
    {
        _someInfo = "ChildInfo1";
    }
    public new string SomeInfo
    {
        get { return _someInfo; }
    }
}



回答3:


You should avoid using "new" in this situation. Define in your derived class, instead, a readonly property in this way:

public override string SomeInfo { get { return "ChildInfo"; } }

You can still set your property but it always will return the default value "ChildInfo".



来源:https://stackoverflow.com/questions/42065110/change-baseclass-property-to-readonly-in-derivedclass-with-new-and-override

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!