2010-11-12 39 views
5

考虑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; 
    } 
} 

然后,后来在代码中,你有:

int x=0, y=0, z=0; 
... 
CoordinateTransformation.TranslateAllCoords(ref x, ref y, ref z, 5); 
... 

但是,通过调用TranslateAllCoords你实际上是修改的值类型(即,整数坐标)并且通常值类型应该是不可变的。是否有一些规则在这里被打破,或者这是一个完全有效的构造,通过修改仅内置的值类型来解决“值类型应该是不可变的”构造?

回答

17

是不可变的。包含值类型的变量是可变的。变量有所不同,这就是为什么他们被称为“变量”。

值类型应该是不可改变的设计指导基本上是说你不应该试图只改变一部分变量。当你说

struct Point { public int X; public int Y; public int Z; } 
... 
Point p = new Point(); 
p.X = 123; 

然后你在说什么是“只改变变量p的一部分”。这是令人困惑的。变量p应逻辑地表示一个点,并且一个点是一个值。如果你想改变p,那么逻辑上改变整个事情分配一个新的点。不要将一点变为另一点。

但是,即使我们做了点不变:

struct Point { public int X { get; private set; } ... etc } 

那么该类型的变量仍然可以改变!

Point p = new Point(123, 456, 789); 
p = new Point(100, 200, 300); 

但现在很显然,整个变量被更改为新的起点,而不是我们试图变异变量的特定部分。

有了一个不变的值类型,那么你可以做你的翻译更理智:

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

见,再次,对变异,但变异它全部一次,而不是在一个时间小位。

+0

感谢您的明确解释! – 2010-11-12 16:34:18

1

那里没有规则。您只需创建一个新的整数值并重新分配包含它们的变量。