2010-01-13 56 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以获取更多信息。

正如其他人所说,如果你真的想要独立的对象,你需要克隆它们。我会建议尝试以另一种方式设计这个,但是,亲自。