27

I have a typed array MyType[] types; and i want to make and independant copy of this array. i tried this

MyType[] types2 = new MyType[types.Length] ;

types2 = types ;

but this create a reference to the first. I then tried

Array.Copy( types , types2 , types.Length ) ;

but I have the same problem: changing a value in the first array changes the value in the copy as well.

How can I make a completely independent or deep copy of an Array, IList or IEnumerable?

8 Answers 8

19

Based on the first post, all he needs is this for "an independent copy of the array". Changes to the shallowCopy array itself would not appear in the types array (meaning element assignment, which really is what he showed above despite saying "deep copy"). If this suits your needs, it will have the best performance.

MyType[] shallowCopy = (MyType[])types.Clone();

He also mentions a "deep copy" which would be different for mutable types that are not recursive value-type aggregates of primitives. If the MyType implements ICloneable, this works great for a deep copy:

MyType[] deepCopy = (MyType[])Array.ConvertAll(element => (MyType)element.Clone());
Sign up to request clarification or add additional context in comments.

Comments

15

For the impatient:

newarray = new List<T>(oldarray).ToArray();

2 Comments

Is there a reason you first create a list and then calling .ToArray() instead of oldarray.ToArray()? Your method will call CopyTo in the List constructor and Copy in ToArray, I'm not sure I see the point
@CervEd Array.ToArray is a LinQ extension, but List<T>.ToArray is natively implemented in List<T>. Some people try to avoid LinQ as much as possible for performance reasons.
10

Implement a clone method on MyType, using protected method MemberwiseClone (performs shallow copy) or using a deep cloning technique. You can have it implement an ICloneable then write several extensions methods that will clone the corresponsing collection.

interface ICloneable<T>
{
    T Clone();
}

public static class Extensions
{
    public static T[] Clone<T>(this T[] array) where T : ICloneable<T>
    {
        var newArray = new T[array.Length];
        for (var i = 0; i < array.Length; i++)
            newArray[i] = array[i].Clone();
        return newArray;
    }
    public static IEnumerable<T> Clone<T>(this IEnumerable<T> items) where T : ICloneable<T>
    {
        foreach (var item in items)
            yield return item.Clone();
    }
}

You must do this because while a new array is created when you use Array.Copy it copies the references, not the objects referenced. Each type is responsible for copying itself.

1 Comment

Microsoft says: we recommend that ICloneable not be implemented in public APIs because it doesn't specify deep vs shallow copy semantics. Better create an own IDeepCopyable interface.
7

If your type is serializable you can use serialization techniques to get a copy of your array (including deep copies of the items):

private static object GetCopy(object input)
{
    using (MemoryStream stream = new MemoryStream())
    {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, input);
        stream.Position = 0;
        return formatter.Deserialize(stream);
    }
}

To use it:

MyType[] items = new MyType[2];
// populate the items in the array

MyType[] copies = (MyType[])GetCopy(items);

1 Comment

my type is not serializable =(
4

I wanted to do the same thing: make a copy of an array by value for things like sorting so that I could later reinitialize another temp array with the original source array. After researching this, I found this cannot be done so simply. So, I made a workaround. I will use my own code below:

string[] planetNames = new string[] { "earth", "venus", "mars" };

string[] tempNames = new string[planetNames.Length];

for (int i = 0; i < planetNames.Length; i++)
{
     tempNames[i] = planetNames[i];
}

planetNames is my source array. tempNames is the array which I will later sort independently of planetNames. I have tested this and this code does not sort planetNames when I sort tempNames which is what I was attempting to achieve.

Comments

3

If you want to create a copy of just an array with references to objects in old array (or if you have array of value type objects), simplest solution is

var newArray = oldArray.ToArray()

If you want deep copy you should have a method which copies single object of your type (e.g. public MyType Copy(MyType obj)). Then solution will look like

var newArray = oldArray.Select(x => Copy(x)).ToArray()

2 Comments

To clarify, Copy(x) is a custom implementation, right?
Yes, there is no method to perform deep copy of object of any type. There is MemberwiseClone method in any object but it is protected and creates only shallow copy (copy of object itself but doesn't create new copies of fields of reference type), not deep copy.
0

I've found if you just want a simple char array copy you can trick C# into doing a copy by value using the char:

char[] newchararray = new char[desiredchararray.Length];

for (int k = 0; k < desiredchararray.Length; k++)
{

   char thecharacter = newchararray[k];
   newchararray[k] = thecharacter;
   oldchararray[k] = oldchararray[k] + 1;

}

Seems to work for me but if anyone disagrees please let me know :)

1 Comment

char is a value type. This will work different for reference types.
0

Copying the value of the array in this case are numbers

int[] arr = { 1, 2, 3, 4, 5 };
int[] copyArr = new int[arr.Length];
for (int i = 0; i <arr.Length; i++)
{
    copyArr[i]=arr[arr.Length-i-1];
}
Console.WriteLine(string.Join(" ",arr));**

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.