1. ホーム
  2. c#

[解決済み] ゲッターのみのプロパティをオーバーライドして、セッターを追加することができないのはなぜですか?[クローズド]

2022-04-30 07:50:29

質問

以下の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 は読み取り専用のプロパティでなければならないと明示的に宣言しているからです。派生物がこの契約を破って読み書きできるようにするのは意味がない。

この件に関しては、マイクロソフトに賛成です。

例えば、私が新人プログラマーで、Baseclassの派生に対抗してコードを書くように言われたとします。私は、Barが書き込めないことを前提としたものを書きました(Baseclassは、それが取得専用プロパティであることを明示しているからです)。 今、あなたの派生を使うと、私のコードは壊れるかもしれません。

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 は変更できないので。しかし、もし派生クラスで設定が可能であれば、誰かが _source オブジェクトの Bar プロパティを外部で変更した場合、このクラスは古い値を提供することができます。ポイントは、' オープンであること、卑怯なことをしないこと、人を驚かせないこと。 '

更新情報 : Ilya Ryzhenkovが問う「なぜインターフェースは同じルールでプレイしないのか? うーん、考えれば考えるほど泥沼化してるなぁ。

インターフェースは、「実装がBarという名前の読み取りプロパティを持つことを期待する」という契約である。 個人的に インターフェイスを見たときに、読み取り専用という前提を立てることはあまりないですね。インターフェースでget-onlyのプロパティを見たとき、私は「どんな実装でもこの属性Barを公開するだろう」と読み取ります。もちろん、技術的には契約を破っているわけではないのだが、それ以上のことをしているわけだ。だから、ある意味正しいんだけどね。最後に「誤解が生じないように、できるだけ難しくする」と言っておこう。