价值类型的可变性

Mic*_*eyn 5 c# c#-4.0

考虑TranslateAllCoords静态函数:

static class CoordinateTransformation
{
  public static void TranslateAllCoords(ref int x, ref int y, ref int z, 
                                        int amount)
  {
    x+=amount;
    y+=amount;
    z+=amount;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,稍后在代码中,您有:

int x=0, y=0, z=0;
...
CoordinateTransformation.TranslateAllCoords(ref x, ref y, ref z, 5);
...
Run Code Online (Sandbox Code Playgroud)

但是,通过调用TranslateAllCoords,您实际上修改了值类型(即整数坐标),通常值类型应该是不可变的.这里是否有一些规则被破坏,或者这是一个完全有效的构造,通过仅修改内置值类型来绕过"值类型应该是不可变的"构造?

Eri*_*ert 17

是不可变的.包含值类型的变量是可变的.变量各不相同,这就是为什么它们被称为"变量".

值类型应该是不可变的设计指南实质上是说你不应该只尝试改变变量的一部分.当你说

struct Point { public int X; public int Y; public int Z; }
...
Point p = new Point();
p.X = 123;
Run Code Online (Sandbox Code Playgroud)

那么你所说的是"只改变变量p的一部分".这令人困惑.变量p应逻辑上表示一个点,而一个点应该是一个值.如果你想改变p,那么通过为它指定一个新点来逻辑地改变整个事物.不要将一个点变异为另一个点.

但即使我们提出了不可改变的观点:

struct Point { public int X { get; private set; } ... etc }
Run Code Online (Sandbox Code Playgroud)

那么这种类型的变量仍然可以变化!

Point p = new Point(123, 456, 789);
p = new Point(100, 200, 300);
Run Code Online (Sandbox Code Playgroud)

但现在很明显,整个变量正在改变到一个新的点,而不是我们试图改变变量的特定部分.

使用不可变值类型,您可以更明智地进行翻译:

static Point Translate(Point p, int offset) 
{
    return new Point(p.X + offset, p.Y + offset, p.Z + offset);
}
...
Point p = new Point(100, 200, 300);
p = Translate(p, 5);
Run Code Online (Sandbox Code Playgroud)

再看看p变异,但它一次变异,而不是一次变异.