繁体   English   中英

在C#中将setter添加到虚拟属性

[英]Adding a setter to a virtual property in C#

我有这样的情况:

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

现在,对于某些派生类,属性值是一个合成值,因此没有setter:

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

这很好用。 但是,某些派生类需要更传统的后备存储。 但是,无论我如何编写它,如在自动属性上,或使用显式的后备存储,我都会收到错误:

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

public class Derived3 : BaseClass
{
    private string myProp;
    public override string MyProp 
    { 
        get { return myProp;} 
        private set { myProp = value;}
    }
}

Derived2.MyProp.set':无法覆盖,因为'BaseClass.MyProp'没有可覆盖的set访问器

我如何让它工作?

您可以做的最好的事情是将属性实现为virtual而不是abstract 为基类中的每个抛出NotSupportedException set getset块,并在派生类中相应地覆盖行为:

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

基本上,你不能。 通过添加setter,您将更改属性的定义,因此它并不真正“覆盖”基本属性。 它就像你试图覆盖一个方法并向其添加另一个参数一样 - 它们将被视为不同的方法(重载)。 由于属性无法重载,因此无效。

您只需添加另一种方法来设置值(可能具有protected可访问性)。

我建议避免使用虚拟或抽象属性。 相反,使用非虚拟属性链接到受保护的虚拟或抽象get / set方法。 这样做将允许派生类覆盖方法,并使用具有不同访问修饰符的属性来遮蔽属性。 由于基本属性本身是非虚拟的,因此永远不需要覆盖它,因此与新版本的命名冲突无关紧要。

布拉德利的建议很好,但是在我只有Setter应该是虚拟的情况下我做过的一件事就是这样做:

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;
    }
}

它需要一些额外的工作,但它似乎保持更高程度的封装(例如,您可以防止子类覆盖Getter行为,并且您的子类不必知道属性背后的底层成员)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM