What’s the difference between the System.Array.CopyTo() and System.Array.Clone()?
12 Answers
The Clone() method returns a new array (a shallow copy) object containing all the elements in the original array. The CopyTo() method copies the elements into another existing array. Both perform a shallow copy. A shallow copy means the contents (each array element) contains references to the same object as the elements in the original array. A deep copy (which neither of these methods performs) would create a new instance of each element's object, resulting in a different, yet identical object.
So the difference are :
1- CopyTo require to have a destination array when Clone return a new array.
2- CopyTo let you specify an index (if required) to the destination array.
Edit:
Remove the wrong example.
6 Comments
numbersCopy is just another reference to the array assigned to numbers. This is not the same as using the CopyTo() method. If you use CopyTo(), you will get the same results as in your Clone() example. Also, this is C# - System.out.println should be Console.WriteLine.ToArray() method provides a much simpler (and typed) way of shallow-cloning an array anyway. Since Array is IENumerable<T> it works on it.One other difference not mentioned so far is that
- with
Clone()the destination array need not exist yet since a new one is created from scratch. - with
CopyTo()not only does the destination array need to already exist, it needs to be large enough to hold all the elements in the source array from the index you specify as the destination.
Comments
As stated in many other answers both methods perform shallow copies of the array. However there are differences and recommendations that have not been addressed yet and that are highlighted in the following lists.
Characteristics of System.Array.Clone:
- Tests, using .NET 4.0, show that it is slower than
CopyToprobably because it usesObject.MemberwiseClone; - Requires casting the result to the appropriate type;
- The resulting array has the same length as the source.
Characteristics of System.Array.CopyTo:
- Is faster than
Clonewhen copying to array of same type; - It calls into
Array.Copyinheriting is capabilities, being the most useful ones:- Can box value type elements into reference type elements, for example, copying an
int[]array into anobject[]; - Can unbox reference type elements into value type elements, for example, copying a
object[]array of boxedintinto anint[]; - Can perform widening conversions on value types, for example, copying a
int[]into along[]. - Can downcast elements, for example, copying a
Stream[]array into aMemoryStream[](if any element in source array is not convertible toMemoryStreaman exception is thrown).
- Can box value type elements into reference type elements, for example, copying an
- Allows to copy the source to a target array that has a length greater than the source.
Also note, these methods are made available to support ICloneable and ICollection, so if you are dealing with variables of array types you should not use Clone or CopyTo and instead use Array.Copy or Array.ConstrainedCopy. The constrained copy assures that if the copy operation cannot complete successful then the target array state is not corrupted.
2 Comments
.ToArray() method. It makes a copy anyway, and it can be executed on any IEnumerable<>, including arrays. And unlike .Clone(), it's typed, so no casting needed.object[] myarray = new object[] { "one", 2, "three", 4, "really big number", 2324573984927361 };
//create shallow copy by CopyTo
//You have to instantiate your new array first
object[] myarray2 = new object[myarray.Length];
//but then you can specify how many members of original array you would like to copy
myarray.CopyTo(myarray2, 0);
//create shallow copy by Clone
object[] myarray1;
//here you don't need to instantiate array,
//but all elements of the original array will be copied
myarray1 = myarray.Clone() as object[];
//if not sure that we create a shalow copy lets test it
myarray[0] = 0;
Console.WriteLine(myarray[0]);// print 0
Console.WriteLine(myarray1[0]);//print "one"
Console.WriteLine(myarray2[0]);//print "one"
3 Comments
Both CopyTo() and Clone() make shallow copy. Clone() method makes a clone of the original array. It returns an exact length array.
On the other hand, CopyTo() copies the elements from the original array to the destination array starting at the specified destination array index. Note that, this adds elements to an already existing array.
The following code will contradict the postings saying that CopyTo() makes a deep copy:
public class Test
{
public string s;
}
// Write Main() method and within it call test()
private void test()
{
Test[] array = new Test[1];
array[0] = new Test();
array[0].s = "ORIGINAL";
Test[] copy = new Test[1];
array.CopyTo(copy, 0);
// Next line displays "ORIGINAL"
MessageBox.Show("array[0].s = " + array[0].s);
copy[0].s = "CHANGED";
// Next line displays "CHANGED", showing that
// changing the copy also changes the original.
MessageBox.Show("array[0].s = " + array[0].s);
}
Let me explain it a bit. If the elements of the array are of reference types, then the copy (both for Clone() and CopyTo()) will be made upto the first(top) level. But the lower level doesn't get copied. If we need copy of lower level also, we have to do it explicitly. That's why after Cloning or Copying of reference type elements, each element in the Cloned or Copied array refers to the same memory location as referred by the corresponding element in the original array. This clearly indicates that no separate instance is created for lower level. And if it were so then changing the value of any element in the Copied or Cloned array would not have effect in the corresponding element of the original array.
I think that my explanation is exhaustive but I found no other way to make it understandable.
Comments
Array.Clone() would perform technically deep copy, when pass the array of int or string to a method as a reference.
For example
int[] numbers = new int[] { -11, 12, -42, 0, 1, 90, 68, 6, -9 };
SortByAscending(numbers); // Sort the array in ascending order by clone the numbers array to local new array.
SortByDescending(numbers); // Same as Ascending order Clone
Even if the methods sort the array of numbers but it wont affect the actual reference passed to the sorting methods.i.e the number array will be in same unsorted initial format in line no 1.
Note: The Clone should be done in the sorting methods.
Comments
The Clone() method don't give reference to the target instance just give you a copy.
the CopyTo() method copies the elements into an existing instance.
Both don't give the reference of the target instance and as many members says they give shallow copy (illusion copy) without reference this is the key.
Comments
Both are shallow copies. CopyTo method is not a deep copy. Check the following code :
public class TestClass1
{
public string a = "test1";
}
public static void ArrayCopyClone()
{
TestClass1 tc1 = new TestClass1();
TestClass1 tc2 = new TestClass1();
TestClass1[] arrtest1 = { tc1, tc2 };
TestClass1[] arrtest2 = new TestClass1[arrtest1.Length];
TestClass1[] arrtest3 = new TestClass1[arrtest1.Length];
arrtest1.CopyTo(arrtest2, 0);
arrtest3 = arrtest1.Clone() as TestClass1[];
Console.WriteLine(arrtest1[0].a);
Console.WriteLine(arrtest2[0].a);
Console.WriteLine(arrtest3[0].a);
arrtest1[0].a = "new";
Console.WriteLine(arrtest1[0].a);
Console.WriteLine(arrtest2[0].a);
Console.WriteLine(arrtest3[0].a);
}
/* Output is
test1
test1
test1
new
new
new */
Comments
Please note: There is a difference between using String[] to StringBuilder[].
In String - if you change the String, the other arrays we have copied (by CopyTo or Clone) that points to the same string will not change, but the original String array will point to a new String, however, if we use a StringBuilder in an array, the String pointer will not change, therefore, it will affect all the copies we have made for this array. For instance:
public void test()
{
StringBuilder[] sArrOr = new StringBuilder[1];
sArrOr[0] = new StringBuilder();
sArrOr[0].Append("hello");
StringBuilder[] sArrClone = (StringBuilder[])sArrOr.Clone();
StringBuilder[] sArrCopyTo = new StringBuilder[1];
sArrOr.CopyTo(sArrCopyTo,0);
sArrOr[0].Append(" world");
Console.WriteLine(sArrOr[0] + " " + sArrClone[0] + " " + sArrCopyTo[0]);
//Outputs: hello world hello world hello world
//Same result in int[] as using String[]
int[] iArrOr = new int[2];
iArrOr[0] = 0;
iArrOr[1] = 1;
int[] iArrCopyTo = new int[2];
iArrOr.CopyTo(iArrCopyTo,0);
int[] iArrClone = (int[])iArrOr.Clone();
iArrOr[0]++;
Console.WriteLine(iArrOr[0] + " " + iArrClone[0] + " " + iArrCopyTo[0]);
// Output: 1 0 0
}
2 Comments
CopyTo vs Clone. It's just reference semantics vs value semantics. int is a value type, so you get a new copy every time. StringBuilder has reference semantics, so you are acting on the same copy.