开发者

Deep Copy with Array

Why doesn't ICloneable's Clone method return a deep copy?

Here is some sample code:

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

In the Main method :

A[] Array1 = new A[4] ;
Array1[0] = new A(0);
Array1[1] = new A(1);
Array1[2] = new A(2);
Array1[3] = ne开发者_开发知识库w 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}");

Remembering that I've only changed element index 2 in Array2, here is the output from the code above, listing the values in Array1:

Index 0 value: 0
Index 1 value: 1
Index 2 value: 11
Index 3 value: 3

Index 2 in Array1 has 11 even though I changed it in Array2 and class A implements ICloneable!

What then is the benefit of Array implementing ICloneable?


From http://msdn.microsoft.com/en-us/library/k4yx47a1.aspx:

"If sourceArray and destinationArray are both reference-type arrays or are both arrays of type Object, a shallow copy is performed. A shallow copy of an Array is a new Array containing references to the same elements as the original Array. The elements themselves or anything referenced by the elements are not copied"

There may be a better method than this, but one technique you could use is:

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


Array.Copy copies the values of the array, in this case, references. There is nothing in the documentation of Array.Copy() that indicates a check for classes that implement IClonable and call Clone() instead. You will need to loop through the array and call Clone() yourself.

BTW, yes, IClonable kind of sucks.


Array.Copy() does not use ICloneable. It simply copies values stored in each cell (which in this case are references to your A objects)


Ani's answer uses LINQ thus does not work for C# 2.0, however a same method can be done using the Array class's ConvertAll method:

A[] Array2 = Array.ConvertAll(Array1,a => (A)a.Clone());
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜