2010-12-03 55 views
44

我不斷收到相同的問題,我想要引用的對象被複制或者我想要複製的對象被引用。當我使用=運算符時會發生這種情況。什麼時候複製了C#值/對象,何時複製了其引用?

例如,如果我發送對象爲另一種形式,即:

SomeForm myForm = new SomeForm(); 
SomeObject myObject = new SomeObject(); 
myForm.formObject = myObject; 

...然後修改表單對象,原來的對象不會被修改。就好像該對象被複制並且未被引用。然而,當我這樣做:

SomeObject myObject = new SomeObject(); 
SomeObject anotherObject = new SomeObject(); 
anotherObject = myObject; 

...然後修改anotherObjectmyObject被修改爲好。

最惱人的情況是,當我試圖克隆我定義的對象之一:

public class SomeObject 
{ 
    double value1, value2; 

    //default constructor here 

    public SomeObject(val1, val2) 
    { 
     value1 = val1; 
     value2 = val2; 
    } 

    public void Clone(SomeObject thingToCopy) 
    { 
     this.value1 = thingToCopy.value1; 
     this.value2 = thingToCopy.value2; 
    } 
} 

當我這樣做......

SomeObject obj1 = new SomeObject(1, 2); 
SomeObject obj2 = new SomeObject(); 
obj2.Clone(obj1); 

... obj1引用和任何修改到obj2更改obj1

系統對象如int, double, string等似乎總是被複制,除了上面的克隆方法。

我的問題是,沒有考慮到ref關鍵字在函數中的使用,什麼時候一個對象被拷貝以及什麼時候一個對象在每個事件中被引用(即當傳遞給函數,當設置爲其他對象(如上面的前兩個例子),複製類似第三個例子的成員變量等)?

回答

32

很難回答這樣的問題,而不用花費大量時間仔細挑選您的文字。

我已經這樣做了一對夫婦,你可能會發現有用的文章:

這並不是說,這些條款是完美的,當然 - 遠非如此 - 但我試圖儘可能清楚。

我認爲一件重要的事情是將兩個概念(參數傳遞和引用與值類型)分開。

看你的具體的例子:

SomeForm myForm = new SomeForm(); 
SomeObject myObject = new SomeObject(); 
myForm.formObject = myObject; 

這意味着myForm.formObjectmyObject指的SomeObject同一個實例 - 就像紙片段中的兩個人,每一個有相同的地址寫在他們。如果你去一張紙上的地址,把房子塗成紅色,然後轉到第二張紙上的地址,你會看到一個紅色的房子。

不清楚你的意思是「然後修改窗體中的對象」,因爲你提供的類型是不可變的。沒有辦法修改對象本身。您可以更改myForm.formObject以引用SomeObject的不同實例,但這就像在一張紙上塗寫地址並在其上寫入不同的地址。這不會改變另一張紙上寫的內容。

如果你可以提供一個簡短但完整程序,其行爲你不明白(理想的是控制檯應用程序,只是爲了讓事情變得更短和更簡單),它會更容易談論具體而言事情。

4

嗨邁克 從ValueType派生的所有對象,如struct或其他基元類型都是值類型。這意味着只要您將它們分配給變量或將它們作爲方法參數傳遞,就會將其複製。其他類型是引用類型,這意味着,當您將引用類型分配給一個變量時,不是它的值,而是將它在內存空間中的地址分配給該變量。 另外你應該注意,你可以使用ref關鍵字來傳遞一個值類型作爲參考。這裏的語法

public void MyMethod(ref int a) { a = 25 } 
int i = 20; 
MyMethod(ref i); //Now i get's updated to 25. 

希望它能幫助:)

+0

對不起,挑選這裏。對象不派生。類型可以。對象通常是用於描述類型實例的術語。 – 2010-12-03 17:07:25

+0

您可以使用`ref`通過*參數傳遞參數*,但這與將*作爲參考傳遞*不同。我認爲這是值得區分兩者之間的。 – 2010-12-03 17:14:59

1

至於克隆的對象,如果你要複製從一個對象到另一個對象的值是引用類型則任何修改,這些值在原來的對象將影響複製對象中的值(因爲它們只是對同一對象的引用)

如果您需要克隆具有引用類型屬性的對象,則需要將這些類型設置爲可克隆對象或執行手動副本他們通過根據需要實例化新實例。

考慮使用IClonable接口,雖然它不是解決方案的最佳解決方案。

相關問題