Clone lists and arrays of objects in C#

This is the last post I'll write about clones, at least for a while. Some collection classes can already make clones. For example, an array can clone itself, although the result is always a shallow clone. This example shows how to add extension methods that allow arrays and lists to make both shallow and deep clones.

The following code shows the new extension methods.

// Return a deep clone of a list.
public static List DeepClone(this List items)
{
    // Make the new list.
    List result = new List();

    // Add items to it.
    foreach (T item in items)
    {
        result.Add(item.DeepClone());
    }
    return result;
}

// Return a deep clone of an array.
public static T[] DeepClone(this T[] items)
{
    // Make the new array.
    T[] result = new T[items.Length];
    
    // Add items to it.
    for (int i = 0; i < items.Length; i++)
    {
        result[i] = items[i].DeepClone();
    }
    return result;
}

// Return a shallow clone of a list.
public static List ShallowClone(this List items)
{
    // Make the new list.
    List result = new List();

    // Add items to it.
    foreach (T item in items)
    {
        result.Add(item);
    }
    return result;
}

// Return a shallow clone of an array.
public static T[] ShallowClone(this T[] items)
{
    return (T[])items.Clone();
}

All of these methods are generic so they take a generic type parameter T that represents the type of the objects in the list or array.

The first method makes a deep clone of a list. It creates a new list holding objects of type T. It then loops through the original list adding clones of the original items to the new list. The code calls the DeepClone extension method described in the post Use serialization to make deep clones of a class in C#. That code requires that the objects being serialized are serializable so this method only works if they are serializable.

An alternative strategy would be to require the type T to implement ICloneable and then invoke the object's Clone method. Unfortunately the Clone method required by ICloneable need not be a deep clone so the result might be a shallow clone in some cases.

The second extension method is similar to the first except it works for an array instead of a list.

The third method makes shallow clones of a list. It creates a new list and copies references to the original items into it.

The final method uses an array's existing Clone method to make a shallow clone of the array. You could simply call that method in your own code--I've wrapped this call in the ShallowClone method for consistency.

   

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments

  • 11/29/2011 9:49 AM E. Anderson wrote:
    You can greatly simplify the code and remove the loops:

    public static List DeepClone(this List items)
    {
    return new List(from x in items select x.DeepClone());
    }

    public static T[] DeepClone(this T[] items)
    {
    return (from n in items select n.DeepClone()).ToArray();
    }

    public static List ShallowClone(this List items)
    {
    return new List(items);
    }

    I've been playing with LINQ for about a year now and find it fascinating. My experience so far is it makes our production code less buggy -- relying on the .NET framework to do the repetitive work -- and easier to maintain.
    Reply to this
Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.