クラス プロパティを構造体であるかのように動作させたい場合がよくあります。(編集:実際には、構造体の仕組みを誤解していました。プロパティを構造体とまったく同じように動作させたくありません。操作とコピーの場合に異なる動作をさせたいのです。)
これが可能かどうか疑問に思っています。可能であれば、それは良い考えでしょうか。
2 つの単純なクラスがあるとします。
public class Cube
{
public Point Center {get ; set;}
... // some more cube properties
}
public class Point
{
public virtual Double X {get {return this.x;} set{this.x = value;}}
public virtual Double Y {...}
public virtual Double Z {...}
...
}
今、私は次のように Cube.Center にアクセスしたいと思います:
Cube cube = new Cube();
cube.Center.X += 10.0; // cube1 should move 10.0 in X direction
Point point = cube.Center;
point.X += 10.0 // cube1 should NOT move here
Cube cube2 = new Cube();
cube2.Center = point;
cube2.Center.Y += 5.0; // cube2 should move, but cube1 should stay in place.
私が理解している限り、クラスではなく構造体である Point の場合、値によって渡され、上記が期待される動作になります。(編集:構造体の仕組みを誤解していました。構造体ではそのようなcube.Center.X += 10.0
ことはできません)
でも:
- 可変構造体は悪です
- オブジェクトには、この小さな例よりも多くのフィールドが含まれる場合があります。Microsoft では、メモリ フットプリントが非常に小さい構造体のみを推奨しています。
最も重要なのは、構造体はクラスから継承できないため、このようなことは構造体では不可能です: キューブ センターの Point のプライベートな子クラスを持つことで、変更されるたびに追加の処理が行われます。
public class Cube { // private child of Point, can only be used by Cube private class cubeCenter: Point { private Cube cube; // The cube this point belongs to public override double X { get {return base.X} // custom setter: whenever X changes, // recalculate the bounding box of the cube set {base.X=value; cube.recalculateBoundingBox();} } ... // + other overrides & constructor } private cubeCenter _center; public Point Center { get {return this._center} set {this._center = new cubeCenter(value, this);} } ... } cube1.Center.X += 10.0; // now cube1 moves AND its bounding box is recalculated.
したがって、私が求めている動作は次のとおりです。 - のようなサブプロパティを変更できるはずcube1.Center.X
です。- これが発生するたびに、自分のカスタムcubeCenter
セッターを実行したい。- ただし、誰かが Center: 全体をつかむPoint p = cube1.Center
と、割り当てられたオブジェクトはPoint
キューブに接続されていない通常のオブジェクトになります。
おそらく暗黙の変換演算子を使用して、これは可能ですか?
これは悪いデザインの選択ですか?他の提案をお待ちしています。
(私が検討したことの 1 つは、これらすべての問題を回避するために Points を不変にすることです。ただし、この場合、中心を変更するための見苦しくない構文を見つけることができません:)
// this is the immutable equivalent to cube1.Center.X += 10.0
cube1.Center = cube1.Center.WithX ( cube1.Center.X + 10.0 )