在 C# 中向虚拟属性添加 setter

发布于 2024-10-01 16:08:58 字数 771 浏览 1 评论 0原文

我有这样的情况:

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

现在,对于某些派生类,属性值是合成值,因此没有设置器:

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' 没有可重写的集访问器

我如何让它工作?

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 
    { 
        get { 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??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

为人所爱 2024-10-08 16:08:58

您能做的最好的事情是将属性实现为virtual而不是abstract。在基类中为每个抛出 NotSupportedException 创建 getset 块,并在派生类中相应地重写行为:

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

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();
    }
}
故事和酒 2024-10-08 16:08:58

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

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

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).

寒江雪… 2024-10-08 16:08:58

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 行为,并且您的子类不必知道属性背后的底层成员)。

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).

沦落红尘 2024-10-08 16:08:58

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文