为什么不可能覆盖一个getter专用属性并添加一个setter?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (13)

微软选择不允许:

public abstract class BaseClass
{
    public abstract int Bar { get;}
}

public class ConcreteClass : BaseClass
{
    public override int Bar
    {
        get { return 0; }
        set {}
    }
}

CS 0546‘ConcreteClass.Bar.set’:无法覆盖,因为‘BaseClass.Bar’没有可过脊的集访问器

提问于
用户回答回答于

因为Baseclass的作者明确声明Bar必须是只读属性。衍生产品违反这一契约并使其读写是没有意义的。

我和微软在这件事上。

假设我是一个新的程序员,被告知要对Baseclass派生进行编码。我编写了一些假设Bar不能被写入的东西(因为Baseclass明确声明它是一个GET唯一属性)。现在,通过您的派生,我的代码可能会中断。

public class BarProvider
{ BaseClass _source;
  Bar _currentBar;

  public void setSource(BaseClass b)
  {
    _source = b;
    _currentBar = b.Bar;
  }

  public Bar getBar()
  { return _currentBar;  }
}

由于无法按照BaseClass接口设置Bar,BarProvider认为缓存是一件安全的事情--因为Bar不能被修改。但是,如果在派生中可以使用set,则如果有人修改了_外部源对象的Bar属性。重点是保持开放,避免做鬼鬼祟祟的事情和让人吃惊的事情。

用户回答回答于

我认为主要的原因是语法太明确,不能以任何其他方式工作。此代码:

public override int MyProperty { get { ... } set { ... } }

非常明显,两个getset是超车。没有set在基类中,所以编译器会抱怨。就像不能覆盖基类中未定义的方法一样,也不能覆盖setter。

编译器应该猜测你的意图,并且只对可以被覆盖的方法应用覆盖(在本例中是getter),但是这违背了C#设计原则之一--编译器不能猜测你的意图,因为它可能在不知情的情况下猜测错误。

我认为下面的语法可能会做得很好,但是正如EricLippert一直说的,即使实现这样一个小特性也是很大的努力。

public int MyProperty
{
    override get { ... }
    set { ... }
}

或者,对于自动实现的属性,

public int MyProperty { override get; set; }

扫码关注云+社区