我经常遇到我希望我的类属性表现得像结构一样的情况。(编辑:实际上,我误解了结构的工作原理。我不希望我的属性表现得完全像一个结构;我希望它在被操作和复制时表现不同。)
我想知道这是否可能,如果可以,这是否是一个好主意。
假设我有 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 where 是一个结构而不是一个类,它将按值传递,上面将是预期的行为。(编辑:我误解了结构的工作原理。类似的东西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
没有连接到立方体的普通对象
这可能吗,也许使用隐式转换运算符?
这是一个糟糕的设计选择吗?我愿意接受其他建议。
(我考虑的一件事是使 Points 不可变以避免所有这些问题。但是在这种情况下,我找不到用于更改中心的不难看的语法:)
// this is the immutable equivalent to cube1.Center.X += 10.0
cube1.Center = cube1.Center.WithX ( cube1.Center.X + 10.0 )