Coder Perfect

In C#, how can I clone a generic list?

Problem

In C#, I have a generic list of objects that I’d like to clone. The objects in the list can be cloned, but there doesn’t appear to be a way to clone the entire list ().

Is there a simple solution to this?

Asked by Fiona

Solution #1

If all of your elements are value types, you can just do:

List<YourType> newList = new List<YourType>(oldList);

However, if they are reference types and you want a deep copy (assuming your elements properly implement ICloneable), you could do something like this:

List<ICloneable> oldList = new List<ICloneable>();
List<ICloneable> newList = new List<ICloneable>(oldList.Count);

oldList.ForEach((item) =>
    {
        newList.Add((ICloneable)item.Clone());
    });

Replace ICloneable and cast with whatever your element type is that implements ICloneable in the aforementioned generics.

If your element type doesn’t support ICloneable but has a copy-constructor, you may do something like this instead:

List<YourType> oldList = new List<YourType>();
List<YourType> newList = new List<YourType>(oldList.Count);

oldList.ForEach((item)=>
    {
        newList.Add(new YourType(item));
    });

Personally, I would avoid ICloneable due to the necessity to ensure that all members have a deep copy. I’d recommend the copy-constructor or a factory method like YourType instead. CopyFrom(YourType itemToCopy) creates a new YourType instance.

A technique might be used to wrap any of these options (extension or otherwise).

Answered by Jeff Yates

Solution #2

You have the option of using an extension technique.

static class Extensions
{
    public static IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable
    {
        return listToClone.Select(item => (T)item.Clone()).ToList();
    }
}

Answered by ajm

Solution #3

Use the GetRange function of the generic List class instead for a shallow copy.

List<int> oldList = new List<int>( );
// Populate oldList...

List<int> newList = oldList.GetRange(0, oldList.Count);

Quoted from: Generics Recipes

Answered by Anthony Potts

Solution #4

public static object DeepClone(object obj) 
{
    object objResult = null;

    using (var ms = new MemoryStream())
    {
        var bf = new BinaryFormatter();
        bf.Serialize(ms, obj);

        ms.Position = 0;
        objResult = bf.Deserialize(ms);
     }

     return objResult;
}

With C# and.NET 2.0, this is one method to achieve it. [Serializable()] is a requirement for your object. The goal is to eliminate all references and replace them with new ones.

Answered by Patrick Desjardins

Solution #5

Simply call to clone a list. ToList(). A shallow copy is created as a result of this.

Microsoft (R) Roslyn C# Compiler version 2.3.2.62116
Loading context from 'CSharpInteractive.rsp'.
Type "#help" for more information.
> var x = new List<int>() { 3, 4 };
> var y = x.ToList();
> x.Add(5)
> x
List<int>(3) { 3, 4, 5 }
> y
List<int>(2) { 3, 4 }
> 

Answered by Xavier John

Post is based on https://stackoverflow.com/questions/222598/how-do-i-clone-a-generic-list-in-c