为什么.NET框架不提供深度复制对象的方法?

GR7*_*GR7 6 .net c# deep-copy

我前几天使用自定义方法深度克隆对象,我知道你可以用不同的方式深度克隆(反射,二进制序列化等),所以我只是想知道:

微软在框架中不包含深层复制方法的原因是什么?

Ser*_*rvy 8

问题比你想象的要困难得多,至少在一般情况下如此.

对于初学者来说,副本不仅是深度还是浅薄,而是一个频谱.

让我们想象一下,我们有一个字符串数组列表,我们想要复制它.

  • 我们从最浅层开始,我们只是将整个事物的引用复制到另一个变量.对另一个变量引用的列表的任何更改都会被另一个变量看到.

  • 所以现在我们去创建一个全新的列表来给第二个变量.对于第一个列表中的每个项目,我们将其添加到第二个列表中.现在我们可以修改从任一变量引用的列表,而不会被另一个变量看到.但是如果我们抓住列表的第一项并更改第一个数组中的字符串,那么两个列表都会看到它!

  • 现在我们正在创建一个新列表,对于第一个列表中的每个数组,我们创建一个新数组,将基础数组中的每个字符串添加到新数组中,并将每个新数组添加到新的清单.现在我们可以改变任一列表中的任何数组而不会看到更改.但是等等,两个列表仍然引用相同的字符串(毕竟它们是值类型;它们内部有一个字符数组用于它们的数据).如果一些卑鄙的人出现并改变其中一个字符串(使用不安全的代码,你实际上可以这样做)会怎么样?所以现在你要用深拷贝复制所有字符串.但是,如果我们不需要那样做呢?如果我们知道没有人会这么说他们会改变字符串怎么办?或者,就此而言,如果我们知道没有任何数组将被突变(或者如果它们将被突变,那么它们应该被两个列表反映出来).

然后当然存在诸如循环引用之类的问题,类中的字段实际上并不代表它的状态(即可能根据克隆需要重新计算的缓存值或派生数据).

实际上你需要拥有每个类型的工具IClonable或一些等价物,并拥有自己的自定义代码来克隆自己.这对于维护语言来说需要做很多工作,特别是因为有很多方法可以克隆复杂的对象.成本会非常高,并且(在少数几个被认为值得实现克隆方法的对象之外)的好处通常是不值得的.作为程序员,您可以根据自己知道的深度来编写自己的逻辑来克隆类型.


Mar*_*rio 5

它类似于在C和C ++中的工作方式(或不工作):

要进行深层复制,您实际上必须知道如何解释不同的数据。在平凡的情况下,提供的浅表副本与深表副本相同。但是,一旦这不再成立,它实际上取决于实现和解释。没有一般的经验法则。

让我们以一个游戏为例:

  • NPC对象具有两个整数作为成员。一个整数表示其健康点,另一个整数表示其唯一ID。
  • 如果克隆NPC,则必须保持运行状况,同时更改唯一ID。这是编译器/运行时无法自行确定的。您必须对此进行编码,实际上是告诉程序“如何复制”。

我可以想到两种可能的解决方案:

  • 添加关键字来表示无法复制的内容。虽然这听起来是个好主意,但并不能真正解决问题。您可以告诉编译器UniqueID一定不要复制,但是同时您不能定义应该如何进行。即使可以,您也可以...
  • 创建复制构造函数(C ++)或复制/克隆对象的方法(例如C#CopyTo())。