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