我正在处理一个简单的应用程序,我有点困惑。我有一个简单struct Point
int x
和int y
。我将它用于Line
public class Line : Shape {
public Line() {
PointA = new Point(x: 0, y: 0);
PointB = new Point(x: 0, y: 0);
}
public Point PointA { get; set; }
public Point PointB { get; set; }
}
和某处
var line = new Line();
line.PointB = new Point(x: 4, y: 2);
Console.WriteLine($"Line start at {line.PointA.GetX()}:{line.PointA.GetY()}; end at {line.PointB.GetX()}:{line.PointB.GetY()}");
for (int i = 0; i < 10; i++) {
line.PointB.IncrementX();
line.PointB.IncrementY();
}
Console.WriteLine($"Line start at {line.PointA.GetX()}:{line.PointA.GetY()}; end at {line.PointB.GetX()}:{line.PointB.GetY()}");
此处需要增加x
的{{1}}和y
,但结果不会改变:
行开始于0:0;以4:2结束 行开始于0:0;以4:2结束
我做错了什么?这看起来很奇怪。是否有一些特定的规则在C#中使用Point
。我知道这是一种价值类型,但我认为这对Point有利。所有示例都使用struct
作为Point。请帮忙?
点:
struct
答案 0 :(得分:6)
Struct是一种值类型。并且它通过值传递(即通过创建所有字段的副本)而不是传递对struct实例的引用。所以当你这样做时
line.PointB.IncrementX()
当你调用PropertyB的getter时,它返回Point的 copy ,它存储在PropertyB支持字段中。然后在复制上调用增量。因此原始价值将保持不变。
进一步阅读:Value and Reference Types,尤其是Mutating Readonly Structs,表示
可变值类型是邪恶的。尝试始终创建值类型 不可变的。
如果你想实际移动线点,你可以做什么?
将点类型更改为class
。然后它将通过引用传递,并且所有方法都将在您存储在Line
的原始点上调用。
将新的(修改的)点实例分配给行
即。你应该存储副本,更改它并分配回来
var point = line.PointB; // get copy
point.IncrementX(); // mutate copy
point.IncrementY();
line.PointB = point; // assign copy of copy
您还可以使Point结构不可变(您可以为值类型做最好的事情):
public struct Point
{
public Point(int x, int y)
{
X = x;
Y = y;
}
public int X { get; }
public int Y { get; }
public Point IncrementX() => new Point(X + 1, Y);
public Point IncrementY() => new Point(X, Y + 1);
public Point Move(int dx, int dy) => new Point(X + dx, Y + dy);
}
现在更改位置看起来像
line.PointB = line.PointB.Move(1, 1);