9

我有这样的情况:

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 访问器

我怎样才能让它工作?

4

4 回答 4

11

您可以做的最好的事情是将属性实现为virtual而不是abstract. 为基类中的每个 throw 创建getand块,并在派生类中相应地覆盖行为:setNotSupportedException

public virtual string MyProp {
    get {
        throw new NotSupportedException();
    }
    set {
        throw new NotSupportedException();
    }
}
于 2010-11-11T05:43:47.927 回答
4

基本上,你不能。通过添加一个设置器,您正在更改属性的定义,因此它不会真正“覆盖”基本属性。这就像你试图重写一个方法并向它添加另一个参数一样——它们将被视为不同的方法(重载)。由于属性不能被重载,这将不起作用。

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

于 2010-11-11T05:35:12.533 回答
0

Bradley 的建议很好,但是在只有 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 行为,并且您的子类不必知道属性背后的底层成员)。

于 2010-11-11T14:15:40.850 回答
0

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

于 2013-07-22T18:22:57.213 回答