Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#从数组返回对象会将指针保留到数组项_C#_.net_.net 3.5_Pointers_C# 3.0 - Fatal编程技术网

C#从数组返回对象会将指针保留到数组项

C#从数组返回对象会将指针保留到数组项,c#,.net,.net-3.5,pointers,c#-3.0,C#,.net,.net 3.5,Pointers,C# 3.0,我有一个列表,我执行以下操作: 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

我有一个
列表
,我执行以下操作:

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

如何避免该指针保留,以便在不更新列表中的属性的情况下更新属性?

您可以使用该方法使对象实现接口,然后:

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

更新:


正如评论部分所指出的,不建议实现
ICloneable
接口,因为它没有指定是执行浅克隆还是深克隆。只需在类中添加一个
Clone
方法。

您到底想做什么?是要更新列表中对象的属性,还是要另一个对象,它是列表中对象的副本,但名称不同

作为提供克隆方法的替代方法,您可以提供复制构造函数

var newObj = new MyObj(List[2]);
newObj.Name = "fred";
您可能可以在一个电话中完成这项工作,具体取决于您想做什么。如果您知道总是要用不同的名称创建一个副本,那么您可能需要执行以下操作

var newObj = new MyObj(List[2],"fred");
并在施工过程中设置名称

但是如果不以某种方式显式地创建一个新对象,您就不能做您想做的事情


但是请注意,如果您的对象具有另一个对象的属性,您可能会遇到“深度复制”问题(这就是为什么不鼓励使用IClonable),因为当您需要在newObj中复制该对象时,您会怎么做?您是否只提供对同一实例的引用?还是你也要复制?如果该对象没有克隆方法/复制构造函数,那么该怎么办?

Jon。在C#中,数组中的项存储为“通过引用”,这意味着您在数组中不持有对象的副本,而是持有指向该对象的引用(一个“指针”)。当您检索元素时,您正在检索引用,因此您现在有两个对同一对象的引用。因为更新值时只有一个对象,所以两个引用都“看到”了新值。为了避免这种情况,您需要复制实例,有几种方法可以做到这一点。正如Darin提到的,您可以让对象实现ICloneable,您也可以让对象实现一个复制构造函数,或者您可以创建一个新对象,并从“旧”数据填充新对象。但是,请注意存在一些问题,主要问题是“深度复制”问题。如果对象包含对其他对象的引用,如何复制这些引用?你是复制参考文献还是追踪参考文献并“深度复制”它们。对此没有单一的答案,只有经典的“视情况而定!”

这与数组或列表本身无关-这只是引用类型的工作方式。下面是一个更简单的演示:

MyObj a = new MyObj();
MyObj b = a;
a.Name = "Test";
Console.WriteLine(b.Name); // Will print "Test"
列表和数组的工作方式相同-存储的值将是引用(假设它们是引用类型的值),而不是对象本身的数据

您可能想阅读我的文章以了解更多信息


正如其他人所说,如果你真的想要独立的对象,你需要克隆它们。不过,我个人建议尝试以另一种方式围绕这一点进行设计。

非常好的评论,谢谢,但这就是我所实现的:

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;
    }

框架设计指南建议不要实现iClonable接口。只需提供一个
Clone
方法。克隆的想法是正确的,但不要实现iClonable。有关详细信息,请参阅。是否有一种快速方法可以将所有属性复制到新对象,而不是手动显式键入所有属性,以防类获得新属性,而克隆方法忘记添加要复制的属性。请参阅
MemberwiseClone
方法。