Back to Blog
C#

C# Array Copy Method: Choosing the Right Approach

c# array copy method: Learn how to copy arrays in C# using Array.Copy, Clone, CopyTo, and LINQ ToArray, and understand shallow vs deep copy behavior.

C#ArraysArray.CopyCloneLINQ
Illustration of copying an array in C# showing source and destination arrays with a copy operation.

When you need to duplicate an array in C#, the c# array copy method you choose determines whether you get a fast shallow copy, a copy into an existing buffer, or a LINQ-based one-liner. The key is understanding that arrays are reference types. Assigning one array variable to another does not copy the data; it copies the reference. Both variables then point to the same array in memory. Any modification through one variable is visible through the other. To create an independent array, you must explicitly copy the elements.

Why Assignment Doesn't Copy an Array

Consider this code:

int[] source = { 1, 2, 3 }; int[] target = source; target[0] = 99; Console.WriteLine(source[0]); // Output: 99

The assignment target = source makes target reference the same array object. Changing target[0] changes the element in the shared array, so source[0] also becomes 99. This is not a copy operation. Any real copy method must allocate a new array and transfer the elements.

The .NET Base Class Library provides several ways to do this. The most common are Array.Copy, Array.Clone, CopyTo, and LINQ's ToArray. Each has different behavior regarding performance, partial copying, and type handling.

Using Array.Copy for Fast, Controlled Copies

Array.Copy is a static method that copies a range of elements from one array to another. It is the most flexible option because it allows you to specify source and destination indices and the number of elements to copy.

int[] source = { 1, 2, 3, 4, 5 }; int[] target = new int[5]; Array.Copy(source, target, source.Length);

This copies the entire source array into target. The method also supports overloads for partial copies:

int[] source = { 1, 2, 3, 4, 5 }; int[] target = new int[3]; Array.Copy(source, 1, target, 0, 3); // target now contains { 2, 3, 4 }

Here, copying starts at source index 1 and writes three elements into target starting at index 0. This overload is useful when you need a subarray or when you want to insert data into a specific position of an existing array.

Array.Copy is implemented as a native memory copy when the element type is a value type like int or double. For reference types, it copies the references themselves, not the objects they point to. This makes it a shallow copy.

Using Clone() for a Simple Shallow Copy

Clone() is an instance method defined on the Array base class. It returns a new array containing a shallow copy of the source array. The return type is object, so you must cast it to the correct array type.

int[] source = { 1, 2, 3 }; int[] target = (int[])source.Clone();

The resulting target is a new array with the same length and the same element values. For value types, this is a true element-wise copy. For reference types, the new array contains the same object references as the source.

Clone() is concise and works well when you need a complete copy and do not care about partial ranges. However, it always copies the entire array. There is no overload to copy a subset. If you need only a portion, Array.Copy or CopyTo is more appropriate.

Using CopyTo for Copying into an Existing Array

CopyTo is an instance method that copies all elements of the current array into a destination array starting at a specified index. It is useful when you already have a destination array allocated and want to merge or place data at a specific position.

int[] source = { 5, 6, 7 }; int[] target = new int[5] { 1, 2, 3, 4, 0 }; source.CopyTo(target, 2); // target now contains { 1, 2, 5, 6, 7 }

The destination array must be large enough to hold the copied elements from the starting index to the end. If it is not, an ArgumentException is thrown. CopyTo is effectively a wrapper around Array.Copy with the source index set to 0 and the length set to the source array's length.

One thing to note: CopyTo is also used to copy arrays into multidimensional arrays, but the behavior differs. For a single-dimensional array, it works as shown above. For multidimensional arrays, the index is a linear index that maps to the underlying storage.

LINQ ToArray for a Clean One-Liner

LINQ's ToArray() extension method is another way to copy an array. It creates a new array from any IEnumerable<T>.

using System.Linq; int[] source = { 1, 2, 3 }; int[] target = source.ToArray();

This is concise and readable, and it works with any sequence, not just arrays. However, it has a few drawbacks compared to the other methods. First, it requires using System.Linq. Second, it introduces an extra abstraction layer that may be slower than Array.Copy or Clone because it goes through the IEnumerable<T> enumeration. For small arrays the difference is negligible, but for large arrays or performance-critical code, the native copy methods are preferable.

ToArray() always produces a new array of the same length and copies all elements. It does not support partial copies. If you need a subset, use Array.Copy with a range.

Shallow vs Deep Copy and Reference Type Elements

All the methods described so far perform a shallow copy. For value types like int, double, or struct, the copy is a true copy of each element. For reference types like string (which is immutable) or custom classes, the copy duplicates the references, not the objects themselves.

Consider a class Person with a mutable Name property:

class Person { public string Name { get; set; } } Person[] source = { new Person { Name = "Alice" } }; Person[] target = (Person[])source.Clone(); target[0].Name = "Bob"; Console.WriteLine(source[0].Name); // Output: Bob

Both arrays point to the same Person object, so modifying the object through one array affects the other. If you need a deep copy, where the objects themselves are duplicated, none of these methods will help. You must implement a custom cloning mechanism, such as serialization or manual construction of new objects.

For most use cases, a shallow copy is exactly what you want when the elements are immutable value types or when sharing object references is acceptable. When you need to isolate changes to the objects themselves, you need a deep copy strategy.

Performance and Memory Considerations

Array.Copy is the most efficient method for copying large arrays because it uses a low-level memory copy operation when the element type is a value type. It avoids per-element iteration and is optimized by the runtime. Clone() is also implemented using a similar internal mechanism, so its performance is comparable to Array.Copy for full-array copies.

CopyTo is slightly less direct because it is an instance method that internally delegates to Array.Copy, but the overhead is minimal. LINQ's ToArray() is the least efficient because it enumerates the source using an iterator and builds a new array dynamically. It also allocates temporary buffers during the enumeration process. For a one-off copy in non-critical code, the readability of ToArray() may be worth the small performance cost. For hot paths or large arrays, prefer Array.Copy or Clone.

Memory allocation is another factor. Every copy method allocates a new array. If you are copying frequently, consider reusing a destination array and using Array.Copy to overwrite its contents. This avoids repeated garbage collection pressure.

Choosing the Right Copy Method

The following table summarizes the key differences:

MethodPartial copyDestination controlPerformanceLINQ dependency
Array.CopyYesYesFastestNo
Clone()NoNoFastNo
CopyToNoYes (index)FastNo
ToArray()NoNoSlowerYes

Use Array.Copy when you need a partial copy, when you want to copy into an existing array at a specific index, or when performance is critical. Use Clone() when you need a simple full copy and do not mind the cast. Use CopyTo when you already have a destination array and want to insert the source at a known position. Use ToArray() when you are already working with LINQ and prefer a concise expression, and when the array size is small enough that the performance difference does not matter.

For reference type elements, remember that all these methods are shallow. If you need deep copying, you must implement it yourself. The choice of copy method is often dictated by whether you need a subset, whether you have a preallocated destination, and whether the extra LINQ overhead is acceptable in your context.

c# array copy method: Practical Usage and Code Examples | RYUSLOG DEV