如何制作数组的浅表副本?

18 .net c#

我将二维数组作为属性传递给我的用户控件.在那里我将这些值存储在另一个二维数组中:

int[,] originalValues = this.Metrics;
Run Code Online (Sandbox Code Playgroud)

后来,我改变了值this.Metrics.但是现在如果我从originalValues中检索值,我会从中获取更改的值this.Metrics.如何制作元素的副本,this.Metrics而不仅仅是获取数组的引用?

Mar*_*k W 31

我不知道从哪里得到这个,但这对我很有用.

public static class GenericCopier<T>    //deep copy a list
    {
        public static T DeepCopy(object objectToCopy)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(memoryStream, objectToCopy);
                memoryStream.Seek(0, SeekOrigin.Begin);
                return (T)binaryFormatter.Deserialize(memoryStream);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 称之为矫枉过正就像召唤超新星"热潮":D (8认同)

Pie*_*kel 29

您可以克隆一个数组,它会复制它:

int[,] originalValues = (int[,])this.Metrics.Clone();
Run Code Online (Sandbox Code Playgroud)

  • 克隆不会进行深层复制(除了int值很小的值类型数组). (31认同)
  • 小秘密:问题是关于一个int数组.除此之外的任何事情都会非常矫枉过正. (13认同)
  • 大声笑,我只是回答一般性问题.为什么要求获取值类型的深层副本? (2认同)

Dan*_*Tao 11

问题的关键在于:

在那里我将这些值存储在另一个二维数组中

这实际上是不准确的.你没有创建一个新的数组; 您将originalValues变量设置相同的数组.有关更详细的说明,请参见下文.


Pieter的回答中的评论中表达的混淆是由于围绕术语"深层复制"的一些不确定性.

在复制对象时,有深度复制和浅层复制.

深度复制涉及复制属于对象的所有数据,这意味着如果对象包含本身很复杂的成员(例如,用户定义的引用类型的实例),那么这些对象也必须进行深度复制(以及他们所有的成员,等等).

浅复制涉及简单地将所有字段从一个对象复制到另一个对象,这意味着如果对象包含引用类型,则只需要复制引用(因此复制的引用将指向相同的对象).

对于您发布的代码:

int[,] originalValues = this.Metrics;
Run Code Online (Sandbox Code Playgroud)

......实际上根本没有复制任何对象.您所做的就是复制一个引用,将this.Metrics(引用)的值赋给变量originalValues(也是引用,指向同一个数组).这与简单的值赋值基本相同,如下所示:

int x = y; // No objects being copied here.
Run Code Online (Sandbox Code Playgroud)

现在,该Array.Clone方法实际上是一个拷贝.但正如彼得所指出的那样,整数数组的"浅"或"深"副本之间确实没有区别,因为整数不是复杂的对象.

如果你有这样的事情:

StringBuilder[,] builders = GetStringBuilders();
StringBuilder[,] builderCopies = (StringBuilder[,])builders.Clone();
Run Code Online (Sandbox Code Playgroud)

...,你最终会得到一个全新的数组(副本,是的),但是包含所有相同StringBuilder对象的数组(所以是一个浅的副本).这是深度与浅度复制发挥作用的地方; 如果您想要一个包含所有对象副本的新数组,则需要进行深层复制.StringBuilderbuilders


Bri*_*ott 9

如果要复制的对象是数组,则可以使用:

Array.Copy(sourceArray, destinationArray, sourceArray.Count)
Run Code Online (Sandbox Code Playgroud)

这将为您提供原始数组的单独副本到目标数组中.