2013-03-06 31 views
-1

我工作在C#項目,我的代碼是財產以後這樣的:爲什麼當數組結構中的所有引用改變時?

public struct Point 
{ 
    public int X; 
    public int[,] arr; 
} 
List<Point> po=new List<Point>(); 
void func() 
{ 
    Point p1; 
    p1.arr = new int[1, 1]; 
    p1.X = 10; 
    p1.arr[0, 0] = 1; 
    func2(p2); 
    p1.X=20; 
    p1.arr[0,0]=10; 
} 
void func2(Point h) 
    { 
     po.Add(h); 
    } 

當我跟蹤這個代碼,並在變更p1.x,我在名單點(x參數)不會改變從FUNC2,但返回當將p1.arr更改爲10時,我列表中的點(arr參數)也會從1更改爲10.爲什麼發生這種情況?如何解決此問題?

+0

它看起來像我只是將一個值添加到列表對象... – Brian 2013-03-06 21:54:55

+1

我不明白 – 2013-03-06 21:55:31

+0

'p2'從哪裏來?錯字? – 2013-03-06 21:56:26

回答

2

結構具有價值語義。這意味着改變p1.x正在改變一個值,而不是一個參考。你有一個你正在改變的本地值p1。當您在中更改值時,您正在更改該值的副本。

+0

那麼說,彼得+1。 – Brian 2013-03-06 21:58:28

1

結構是C#中的值類型,而類是引用。嘗試通過ref修飾符將該點傳遞給func2。

void func2(ref Point h){ 
    .... 
} 

實際上,由於JG在SD的評論,應該更像是這樣的:

void func2(ref Point po, Point h){ 
    po.Add(h); 
} 

,並就進一步審查,這仍然是錯誤的。基本上,當您將點添加到列表中時,它將按值將點複製到列表中。

p1和po.Last()具有相同的值,但指的是不同的對象。如果Point是一個班,你就不會有這個問題。

你可以添加P1到後埔這樣做的權利,但它是愚蠢和笨拙:

po.Add(p1); 
var len = po.Count; 
po[len-1].X = 20; 
po[len-1].arr[0,0]=10; 

你不能做:

po.Add(p1); 
var len = po.Count; 
var pNew = po[len-1]; 
// p1 and pNew are different objects in memory, but with the same values 
pNew.X = 20; 
pNew.arr[0,0]=10; 

當然,從技術上,你就可以這樣做,但由於它們在記憶中是不同的物體,所以它不會做你想要的。

只要切換指向一個班級,除非你有嚴重的需要不這樣做。

+0

這不會像你所想的那樣工作,因爲這個值沒有通過引用'List .Add'來傳遞。 – 2013-03-06 22:18:19

+0

@JininSD:這是因爲給出的代碼不會首先編譯。寶來自哪裏?我認爲應該有一個叫做po的第二個Point參數,它應該作爲ref傳入,而h不應該是。更新我的答案以反映這一點。謝謝。 – 2013-03-06 22:52:38

+0

這是我的理解,'po'是'func'之前聲明的成員變量。但是底層的問題仍然存在,在添加到列表之後對「Point」結構所做的任何更改都不會反映在列表內的實例上,因爲沒有列表 .Add(ref T item )'功能。 – 2013-03-06 23:05:25

相關問題