2010-11-12 57 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

那裏沒有規則。您只需創建一個新的整數值並重新分配包含它們的變量。