Home All Groups Group Topic Archive Search About

Array.Copy and Cloning an array don't seem to work differently

Author
28 Aug 2006 11:00 PM
illegal.prime
I would like to have an array of objects (whose class I define) and
then just invoke either:
MyClass [] clonedArray = (MyClass[]) myArray.Clone();
OR
Array.Copy(myArray, clonedArray, myArray.Length);

and have an array of cloned objects (i.e. the new array of objects
aren't the objects contained in my original array).  But instead it
seems necessary for me to have to iterate over my entire array and
individually clone each element in the array.  I thought at least
Array.Copy would do this for me.  Does anyone know why it doesn't or if
I'm missing something that would make this idea work?  Or do I actually
have to manually iterate over my array to achieve this?

Here is the test code so you can see what I mean:

class TestPair : ICloneable
{
    public string a;
    public string b;

    public TestPair (string aParam, string bParam)
    {
        a = aParam;
        b = bParam;
    }

    public object Clone()
    {
        return new TestPair(a, b);
    }
}

public static void TestCloneOfClassWithPair()
{
    TestPair testCloneOfPair1 = new TestPair("blah", "meh");

    TestPair [] testPairs = new TestPair[1];
    testPairs[0] = testCloneOfPair1;

    // the following tries to use the Clone method of the array
    //TestPair [] testCloneOfPairs =  (TestPair [])testPairs.Clone();
    // the following tries using Array.Clone
    /*TestPair [] testCloneOfPairs =  new TestPair[testPairs.Length];
    Array.Copy(testPairs, testCloneOfPairs, testCloneOfPairs.Length);*/
    // Only the following actually succeeds in giving me an array of
elements that don't reference the original array
    TestPair [] testCloneOfPairs =  new TestPair[testPairs.Length];
    for (int i = 0;i < testPairs.Length;i++)
    {
        testCloneOfPairs[i] = (TestPair)testPairs[i].Clone();
    }

    if (testPairs[0] == testCloneOfPairs[0])
        Trace.WriteLine("same object is referenced");

    testCloneOfPairs[0].a = "new value";
    Trace.WriteLine("testPairs - a: "+testPairs[0].a+" b:
"+testPairs[0].b);
}

Suggestions of why neither of the two other techniques succeed?

Thanks,
Novice

Author
28 Aug 2006 11:13 PM
Bruce Wood
illegal.pr***@gmail.com wrote:
Show quote
> I would like to have an array of objects (whose class I define) and
> then just invoke either:
> MyClass [] clonedArray = (MyClass[]) myArray.Clone();
> OR
> Array.Copy(myArray, clonedArray, myArray.Length);
>
> and have an array of cloned objects (i.e. the new array of objects
> aren't the objects contained in my original array).  But instead it
> seems necessary for me to have to iterate over my entire array and
> individually clone each element in the array.  I thought at least
> Array.Copy would do this for me.  Does anyone know why it doesn't or if
> I'm missing something that would make this idea work?  Or do I actually
> have to manually iterate over my array to achieve this?
>
> Here is the test code so you can see what I mean:
>
> class TestPair : ICloneable
> {
>     public string a;
>     public string b;
>
>     public TestPair (string aParam, string bParam)
>     {
>         a = aParam;
>         b = bParam;
>     }
>
>     public object Clone()
>     {
>         return new TestPair(a, b);
>     }
> }
>
> public static void TestCloneOfClassWithPair()
> {
>     TestPair testCloneOfPair1 = new TestPair("blah", "meh");
>
>     TestPair [] testPairs = new TestPair[1];
>     testPairs[0] = testCloneOfPair1;
>
>     // the following tries to use the Clone method of the array
>     //TestPair [] testCloneOfPairs =  (TestPair [])testPairs.Clone();
>     // the following tries using Array.Clone
>     /*TestPair [] testCloneOfPairs =  new TestPair[testPairs.Length];
>     Array.Copy(testPairs, testCloneOfPairs, testCloneOfPairs.Length);*/
>     // Only the following actually succeeds in giving me an array of
> elements that don't reference the original array
>     TestPair [] testCloneOfPairs =  new TestPair[testPairs.Length];
>     for (int i = 0;i < testPairs.Length;i++)
>     {
>         testCloneOfPairs[i] = (TestPair)testPairs[i].Clone();
>     }
>
>     if (testPairs[0] == testCloneOfPairs[0])
>         Trace.WriteLine("same object is referenced");
>
>     testCloneOfPairs[0].a = "new value";
>     Trace.WriteLine("testPairs - a: "+testPairs[0].a+" b:
> "+testPairs[0].b);
> }
>
> Suggestions of why neither of the two other techniques succeed?

By definition, default copies / clones are all shallow. You want a deep
copy.

In order to achieve this you have to either:

a) Define a static method in your TestPair class that clones an array:

public static TestPair[] CloneArray(TestPair[])
{
    ...
}

and then TestPair[] clone = TestPair.CloneArray(original);

or b) Define a whole new class that is a collection of TestPairs and
write a Clone method for it:

public class TestPairCollection ...
{
    public object Clone()
    {
        ...
    }
}

AddThis Social Bookmark Button