开发者

Adding a setter to a virtual property in C#

开发者 https://www.devze.com 2023-01-24 06:42 出处:网络
I have a situation like this: public abstract class BaseClass { public abstract string MyProp { get; } }

I have a situation like this:

public abstract class BaseClass 
{
   public abstract string MyProp { get; }
}

Now, for some of the derived classes, the properties value is a synthesized values, so there is no setter:

public class Derived1 : BaseClass
{
    public override string MyProp { get { return "no backing store"; } }
}

This works fine. However, some of the derived class required a more traditional backing store. But, no matter how I write it, as on automatic property, or with an explicit backing store, I get an error:

public class Derived2 : BaseClass
{
    public override string MyProp { get; private set;}
}

public class Derived3 : BaseClass
{
    private string myProp;
    public override string MyProp 
    { 
        g开发者_运维百科et { return myProp;} 
        private set { myProp = value;}
    }
}

Derived2.MyProp.set': cannot override because 'BaseClass.MyProp' does not have an overridable set accessor

How do I get this to work??


The best thing you can do is implement the property as virtual instead of abstract. Make the get and set blocks for each throw NotSupportedException in the base class and override the behaviour accordingly in derived classes:

public virtual string MyProp {
    get {
        throw new NotSupportedException();
    }
    set {
        throw new NotSupportedException();
    }
}


Basically, you cannot. By adding a setter you are changing the definition of the property, so it does not really "override" the base property. It's the same as if you tried to override a method and add another parameter to it - they would be treated as different methods (overloaded). Since properties cannot be overloaded this won't work.

You'll just have to add another method to set the value (perhaps with protected accessibility).


Bradley's suggestion is good, but one thing I've done in cases where only the Setter should be virtual is to do something this this:

public class Root
{
    private string _MyProp;
    public string MyProp 
    {
        get { return _MyProp;}
        set { _MyProp = SetMyProp(value); }
    }
    protected virtual string SetMyProp(string suggestedValue)
    {
        return suggestedValue;
    }
}
public class Child
    : Root
{
    protected override string SetMyProp(string suggestedValue)
    {
        string oReturn = base.SetMyProp(suggestedValue);
        // Do some sort of cleanup here?
        return oReturn;
    }
}

It requires a little extra work up front, but it seems to maintain a higher degree of encapsulation (e.g. you can prevent subclasses from overriding the Getter behavior, and your subclass doesn't have to be aware of the underlying member behind the property).


I would suggest avoiding virtual or abstract properties. Instead, use a non-virtual property which chains to protected virtual or abstract get/set methods. Doing that will allow derived classes to override the methods and also shadow the property with one that has different access modifiers. Since the base property itself will be non-virtual, there will never be any need to override it, so the naming conflict with the new version won't matter.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号