为什么不允许以下C#代码:
public abstract class BaseClass { public abstract int Bar { get;} } public class ConcreteClass : BaseClass { public override int Bar { get { return 0; } set {} } }
CS0546’ConcreteClass.Bar.set’:无法覆盖,因为’BaseClass.Bar’没有可覆盖的集合访问器
因为Baseclass的作者已明确声明Bar必须是只读属性。推导打破合同并使其可读写是没有意义的。
我在这一点上与Microsoft合作。 假设我是一位新程序员,被告知要针对Baseclass派生进行编码。我写的东西假定Bar不能被写入(因为Baseclass明确声明它是一个get only属性)。现在,根据您的推导,我的代码可能会损坏。例如
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,则如果有人在外部修改_source对象的Bar属性,则此类可以提供陈旧的值。关键是“ 要开放,避免做鬼sneak的事情和让人惊讶的事情 ”
更新 : Ilya Ryzhenkov问:“为什么接口不遵循相同的规则?” 嗯..我想到这变得更加泥泞。 接口是一个合同,上面写着“期望实现具有名为Bar的读取属性”。 就 我 个人而言 ,如果看到接口,则不太可能将其假设为只读。当我在接口上看到get-only属性时,我将其读取为“任何实现都会公开此属性Bar”……在它单击的基类上,因为“ Bar是只读属性”。当然,从技术上讲,您并没有违反合同。因此,您在某种意义上是正确的。.最后,我要说:“使误解变得越来越难”。