C#中的struct没有按预期工作

时间:2017-01-27 23:35:16

标签: c# struct

我正在处理一个简单的应用程序,我有点困惑。我有一个简单struct Point int xint 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

1 个答案:

答案 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);