2010-01-13 57 views
3

我有一個List<T>,我做到以下幾點:C#從Array返回對象離開指針數組項

var myObj = List[2]; //Return object at position 2 
myObj.Name = "fred"; //If you look at List[2] its name has changed to fred 

我嘗試以下,但它仍然在名單

var newObj = new MyObj(); 
var myObj = List[2]; //Return object at position 2 
newObj = myObj; 
newObj.Name = "fred"; //If you look at List[2] its name has still changed to fred 

更新項目我怎樣才能避免這個指針剩下,所以我可以更新屬性,而不用更新它在列表中?

回答

1

大的意見,謝謝,不過這是我已經實現:

public MyObj Clone() 
    { 
     BinaryFormatter bFormatter = new BinaryFormatter(); 
     MemoryStream stream = new MemoryStream(); 
     bFormatter.Serialize(stream, this); 
     stream.Seek(0, SeekOrigin.Begin); 
     MyObj newObj = (MyObj)bFormatter.Deserialize(stream); 
     return newObj; 
    } 
3

你可以使使用MemberwiseClone方法,然後你的對象實現ICloneable接口:

var myObj = List[2]; 
var newObj = myObj.Clone(); 
newObj.Name = "fred"; 

UPDATE:

正如在評論部分中指出,不建議實施ICloneable接口,因爲它不指定它是否執行淺層或深層克隆。只需在課堂上添加Clone方法即可。

+1

框架設計指南建議對實現ICloneable接口。只需提供一個「克隆」方法。 – dtb 2010-01-13 09:52:37

+1

克隆的想法是正確的,但不要實現ICloneable。有關詳細信息,請參閱http://blogs.msdn.com/brada/archive/2003/04/09/49935.aspx。 – 2010-01-13 09:53:06

+0

是否有一種快速方法將所有屬性複製到新對象,而不是手動輸入所有屬性,以防萬一類遇到新屬性並且克隆方法忘記添加該屬性以進行復制。 – Jon 2010-01-13 09:58:48

1

你究竟想幹什麼?你想要更新列表中的對象的屬性,還是希望另一個對象是列表中對象的副本,但名稱不同?

作爲提供克隆方法的替代方法,您可以提供複製構造函數。

var newObj = new MyObj(List[2]); 
newObj.Name = "fred"; 

您可能可以在一次調用中完成此操作,具體取決於您想要執行的操作。如果你知道你總是會只是一個不同的名稱創建一個副本,那麼你可能要像做

var newObj = new MyObj(List[2],"fred"); 

,並在施工過程中設置的名稱。

但沒有以某種方式明確創建新對象,你不能做你想做的。

請注意,如果您的對象有一個屬性是另一個對象,那麼您可能會陷入「深層複製」問題(這就是爲什麼IClonable不鼓勵),因爲您需要複製該對象時該做什麼在你newObj?你只是提供對同一個實例的引用嗎?或者你也複製它?如果該對象沒有克隆方法/拷貝構造函數,那麼該怎麼做?

1

Jon。在C#中,數組中的項目是「通過引用」存儲的,這意味着您不需要在數組中持有對象的副本,而是持有對其的引用(「指針」)。當您檢索要檢索引用的元素時,現在您有兩個對同一對象的引用。由於您在更新值時只有一個對象,因此兩個引用都會「查看」新值。爲了避免這種情況,您需要複製實例,並且有幾種方法可以執行此操作。正如達林提到的,你可以讓對象實現ICloneable,你也可以和對象實現一個拷貝構造函數,或者你可以創建一個新對象並從「舊」數據中填充新對象。但是,請注意有問題,主要問題是「深層複製」問題。如果你的對象持有對其他對象的引用,你如何複製這些對象?你是否複製了參考文獻,或者你是否將參考文獻追溯到「深層複製」那些參考文獻中。對此沒有單一的答案,只是經典的「它取決於!」。

2

這與數組或列表本身無關 - 只是參考類型如何工作。這裏有一個簡單的演示:

MyObj a = new MyObj(); 
MyObj b = a; 
a.Name = "Test"; 
Console.WriteLine(b.Name); // Will print "Test" 

列表和數組的工作方式相同 - 存儲將是參考值(假設他們是引用類型值),而不是對象本身的數據。

您可能想要閱讀我的article about reference types and value types以獲取更多信息。

正如其他人所說,如果你真的想要獨立的對象,你需要克隆它們。我會建議嘗試以另一種方式設計這個,但是,親自。