使用数组进行深拷贝

8
为什么ICloneable接口的Clone方法不返回深度复制?以下是示例代码:
class A : ICloneable 
{
    public int x = 2;
    public A(int x)
    {
       this.x = x; 
    }
       
    public A copy()
    {
        A a = new A(this.x);
        return a; 
    }

     public object Clone()
     {
         A a = new A(this.x);
         return a;
     }
}

Main方法中:
A[] Array1 = new A[4] ;
Array1[0] = new A(0);
Array1[1] = new A(1);
Array1[2] = new A(2);
Array1[3] = new A(3);
A[] Array2 = new A[10];
Array. Copy(Array1, Array2, 4); 

Array2[2].x = 11; 
for (int i = 0; i < 4; i++)
    Console.WriteLine($"Index {i} value: {Array1[i].x}");

请记住,我只改变了Array2中的第二个元素索引,这里是上述代码的输出,列出了Array1中的值:

Index 0 value: 0
Index 1 value: 1
Index 2 value: 11
Index 3 value: 3
< p > 在 Array1 中,索引2的值为11,尽管我已经在Array2中更改了它,并且类A实现了ICloneable!< /p > < p >那么,Array实现ICloneable有什么好处呢?< /p >
4个回答

13

http://msdn.microsoft.com/en-us/library/k4yx47a1.aspx获得以下内容:

“如果sourceArray和destinationArray都是引用类型数组或都是Object类型的数组,则执行浅层复制。 数组的浅表副本是一个新数组,其中包含对原始数组相同元素的引用。 元素本身或由元素引用的任何内容都不会被复制”。

可能有比这更好的方法,但你可以使用的一种技术是:

  A[] array2 = array1.Select (a =>(A)a.Clone()).ToArray();

1
但需要注意的是,在一般情况下,实现 ICloneable 接口并不能保证克隆出来的对象是深拷贝。根据官方文档所述:“ICloneable 接口只要求您实现 Clone() 方法返回当前对象实例的副本。它不指定克隆操作是否执行深度复制、浅表复制或介于两者之间的某种操作。” - ruffin

2
Ani的答案使用了LINQ,因此不能在C# 2.0中工作,然而可以使用Array类的ConvertAll方法来完成相同的操作:
A[] Array2 = Array.ConvertAll(Array1,a => (A)a.Clone());

2

Array.Copy复制数组的值,本例中是引用。在Array.Copy()的文档中没有任何指示说明它会检查实现IClonable接口并调用Clone()的类。您需要循环遍历数组并自行调用Clone()。

顺便说一下,是的,IClonable有点糟糕。


2

Array.Copy() 不使用 ICloneable 接口。它只是复制存储在每个单元格中的值(在此情况下为对您的 A 对象的引用)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接