【发布时间】:2012-08-08 21:11:14
【问题描述】:
我经常遇到我希望我的类属性表现得像结构一样的情况。 (编辑:实际上,我误解了结构的工作原理。我不希望我的属性表现得完全像一个结构;我希望它在被操作和复制时表现不同。)
我想知道这是否可能,如果可以,这是否是个好主意。
假设我有 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 这样的东西不适用于结构)
但是:
- mutable structs are evil
- 对象可能包含比这个小示例更多的字段,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 setter 执行。
- 但是,当有人抓住整个中心时: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 )
【问题讨论】:
标签: c# oop design-patterns properties