2

在开始之前,我知道还有其他几个问题可以“回答”这个问题,但不是以我能完全理解的方式。这就是我所指的: C# 中的深度复制

为什么在 C# 中复制是一个糟糕的主意

我做了一些研究,我希望有人可以向我解释如何将对象设置为另一个对象的值。

例如,假设:

myObject bob;
bob = new myObject();
myObject joe
joe = bob

根据我的研究,joe现在指向鲍勃的bob. 这些对象仍然独立运行吗?

我将如何创建两个对象,将一个对象的内容复制到另一个对象,并使它们成为两个单独的对象,它们的字段、方法和事件分别发生?

很抱歉再次问这个问题,但我似乎无法在其他任何地方找到对我有意义的解释。

4

4 回答 4

6

它们都指向同一个实例。如果您想要两个单独的实例,请使用new运算符创建第二个。

于 2013-10-16T19:39:53.357 回答
3

让我们遍历每一行:

myObject bob; // Creates a variable of type myObject, but it doesn't point anywhere
bob = new myObject(); // bob now points to a newly created myObject instance
myObject joe; // Creates a variable of type myObject, but it doesn't point anywhere
joe = bob; // joe now refers to the same object as bob

要记住的重要一点是,最后一行复制了引用本身的值。比如如果bob指向地址1000,joe也会指向那里。因此,如果您更改此地址的任何数据,两者joebob都将指向相同的数据。

但是,欢迎您设置joe指向其他地方,它不会影响bob. 换句话说:

joe = null; // This will not null out bob

如果你想创建一个全新的实例myObject,你必须这样做:

joe = new myObject(); // This will also not affect bob

现在,如果您尝试myObject在内存中创建一个新实例并复制现有实例的所有属性,您必须自己执行此操作:

joe = new myObject();
joe.X = bob.X; // Assuming X is not a reference itself
joe.Y = bob.Y; // ...or you'd have to do this recursively

.NET 不提供为您进行此复制的方法。一种常见的模式是为它创建一个构造函数,myObject()它接受一个实例myObject并复制其所有属性:

joe = new myObject(bob);
于 2013-10-16T19:41:57.163 回答
2

您在这里将数据与方法混淆了。数据定义了对象是什么。例如A circleof radius2。方法作用于该数据,例如,IncreaseRadius()当您复制时,复制的是该数据,而不是方法。方法只是对类数据进行操作并产生特定于类数据的输出。

不,它们都指向同一个对象。bob并且joe只是 2 个变量,它们在内存中持有对同一对象的引用。如果您通过更改数据bob并从中读取joe,您将获得新的价值。

标准方法是实现ICloneable接口并使用它来创建深层副本。我的意思是你必须在Clone方法中创建一个新对象并将每个数据成员复制到新创建的对象。如果数据是另一种引用类型,那么您也必须克隆它。

于 2013-10-16T19:47:37.163 回答
2

是的,bob并且joe都将指向那里完全相同的对象。

对象的复制确实需要在每个类的基础上完成。假设您有一个只有值类型(可能是一些整数和字符串)的类。复制其中的每个字段都可以。

但是现在想象一下,如果您的类包含对其他对象的引用(很可能),如果您只是逐个字段地复制此对象,您现在将有两个不同的实例共享一些数据(一个打开的文件、一个网络套接字等)。因此,要可靠地复制一个对象,您应该让该对象创建一个自身的副本,因为它知道它拥有什么样的数据。

所以答案是在 C# 中没有安全的通用方法来复制对象。

于 2013-10-16T19:42:28.077 回答