◆ 同じ名前のプロパティ作って例外投げるようにした

いきなりですがこのときの b.x と b.y プロパティはどうなってるでしょう
class A { public int x { get; set; } }
class B : A
{
    private int x { get; set; }
    public int y { get { return this.x; } set { this.x = value; } }
}

var b = new B();
b.x = 1;
b.y = 2;




結果は

Console.WriteLine(b.x);
// 1
Console.WriteLine(b.y);
// 2

x プロパティへのアクセスは B クラスの x が private で見えないので A クラスの方にアクセスされます
y プロパティへのアクセスは getter/setter からは B.x が見えるので A ではなく B の x に値が保存されます

意外と複雑


では今回やりたいことですが
親クラスとほぼ一緒でちょっと機能追加したクラスが欲しかったので 継承して作りました
ただ 親クラスのプロパティで直接アクセスしないでほしいものがあるけどどうやって隠そうか というものです

私としては上のコードで B.x にアクセスしたら A.x にアクセスできるのじゃなくて B.x は private ですよー ってエラーになってほしかったです


最終的に あれこれやってみてとりあえずこうなりました
class A { public int x { get; set; } }
class B : A
{
    public int x { get { throw new InvalidOperationException("このプロパティはアクセス禁止です"); } private set { } }
}

var b = new B();
Console.WriteLine(b.x);
このプロパティはアクセス禁止です
  + Submission#20.B.get_x()

補完の候補に出るのは諦めて 例外を投げるようにしました
プロパティは public でアクセッサの片方を private にした場合は 親クラスが使われることがなく アクセスエラーになるので set のほうは private にしてちょっと楽してます


ただし この方法は完璧というわけじゃないです
A が virtual じゃないので
var b = new B();
((A)b).x = 22;
Console.WriteLine(((A)b).x);
// 22

こんなことができます

でも private でもやろうとすればリフレクションで取得や設定できるんだし 絶対にできなくは無理だと思いますし する必要ないと思います

普通に使おうとしたらエラーがでるなど 使えなくなっていて このプロパティは使うべきじゃないって わかるだけで十分です