744

I have a generic list of objects in C#, and wish to clone the list. The items within the list are cloneable, but there doesn't seem to be an option to do list.Clone().

Is there an easy way around this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Fiona
  • 7,747
  • 4
  • 19
  • 8
  • 56
    You should say if you're looking for a deep copy or a shallow copy – orip Nov 23 '08 at 10:25
  • 13
    What are deep and shallow copies? – Colonel Panic Sep 27 '12 at 11:03
  • 6
    @ColonelPanic http://en.wikipedia.org/wiki/Object_copy#Shallow_copy – Nathan Koop Oct 13 '12 at 20:24
  • 3
    @orip Isn't `clone()` by definition a deep copy? In C# you can pass pointers around easily with =, I thought. – Chris Dec 18 '12 at 20:51
  • 17
    @Chris a shallow copy copies one level deeper than pointer copy. Eg a shallow copy of a list will have the same elements, but will be a different list. – orip Dec 18 '12 at 22:15
  • 3
    Where a deep copy will be a new list, with new items, but the contents are the same. –  Nov 24 '15 at 16:00
  • 1
    Check this [Answer](https://stackoverflow.com/a/52097307/4707576): https://stackoverflow.com/a/52097307/4707576 about: Cloning objects without Serialization – BenSabry Aug 30 '18 at 12:40

29 Answers29

683

If your elements are value types, then 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());
    });

Obviously, replace ICloneable in the above generics and cast with whatever your element type is that implements ICloneable.

If your element type doesn't support ICloneable but does have a copy-constructor, you could do 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 because of the need to guarantee a deep copy of all members. Instead, I'd suggest the copy-constructor or a factory method like YourType.CopyFrom(YourType itemToCopy) that returns a new instance of YourType.

Any of these options could be wrapped by a method (extension or otherwise).

Jeff Yates
  • 61,417
  • 20
  • 137
  • 189
  • 1
    I think List.ConvertAll might look nicer than creating a new list and doing a foreach+add. – MichaelGG Oct 21 '08 at 17:42
  • Good point. I must admit, I'm still coming to grips with all the LINQ calls myself. – Jeff Yates Oct 22 '08 at 15:57
  • +1 So in summary, it is impossible to provide a deep clone function for a Generic.List. Is that right? – Dimitri C. Sep 09 '10 at 10:12
  • 2
    @Dimitri: No, that's not true. The problem is, when `ICloneable` was defined, the definition never stated whether the clone was deep or shallow, so you cannot determine which type of Clone operation will be done when an object implements it. This means that if you want to do a deep clone of `List`, you will have to do it without `ICloneable` to be sure it is a deep copy. – Jeff Yates Sep 10 '10 at 14:36
  • 7
    Why not use the AddRange method? (`newList.AddRange(oldList.Select(i => i.Clone())` or `newList.AddRange(oldList.Select(i => new YourType(i)`) – phoog Dec 21 '10 at 16:00
  • @phoog: It's another option, sure. It doesn't make much difference. – Jeff Yates Dec 21 '10 at 18:04
  • @Jeff Yates: It does make a difference if the collection argument to AddRange implements ICollection. In that case, the list uses the collection's count property so it doesn't have to increase its capacity more than once. This (potentially) saves on memory allocations. In most contexts, of course, the savings is negligible, so for the most part, you're right, it doesn't make much difference. – phoog Dec 21 '10 at 19:43
  • @phoog: That's an optimization I'd avoid unless it was clear from profiling that it was needed. – Jeff Yates Dec 21 '10 at 20:36
  • @Jeff Yates: Fair enough. I've been working with an application that uses huge lists whose arrays are big enough to be in the large object heap, so it's a useful optimization in that case. I'm curious though, why you would avoid it. – phoog Dec 21 '10 at 22:37
  • 5
    @phoog: I think that it is a little less readable/understandable when scanning the code, that's all. Readability wins for me. – Jeff Yates Dec 22 '10 at 15:18
  • why not use ToArray() - that does create a deep copy - it uses memmove effectively – markmnl May 30 '11 at 04:21
  • @Feanor: That's not exactly true. It copies the values of the immediate elements, but what about child values? How does it know if each reference in my type should be its own unique copy or a shared instance? It doesn't. A deep copy is one that traverses the entire object graph for an instance and makes sure that all things it contains or references are also copies and that their references are copies, etc. etc. – Jeff Yates May 30 '11 at 19:46
  • yes, of course you are right, sorry, it is very unlikely the class only consists of value types – markmnl May 31 '11 at 01:08
  • 2
    @JeffYates: One insufficiently-considered wrinkle is that things generally only need to be copied if there exists some execution path which would mutate them. It's *very* common to have immutable types hold a reference to an instance of mutable type, but never expose that instance to anything that will mutate it. Needless copying of things that aren't ever going to change can sometimes be a *major* performance drain, increasing memory usage by orders of magnitude. – supercat Sep 23 '13 at 21:25
  • @supercat: Indeed, it is up to you to determine what needs to be cloned when cloning an object, which is yet another reason why cloning can be so difficult to get right. – Jeff Yates Sep 24 '13 at 15:54
  • @JeffYates: What's unfortunate about that is that the rules aren't complicated--they just depend upon something the type system doesn't have any standard way of expressing. If the type system could decorate *storage location types* with a couple flag attributes to indicate whether they encapsulate identity, mutable state, both, or neither, efficient and reliable deep cloning would be easy in 99% of cases, even for objects that are inherently not serializable. Note that those should be traits of storage location types, not heap types, and not fields. – supercat Sep 24 '13 at 17:06
  • If an `Identity` was regarded as a reference to a `T` used to encapsulate identity only, and a `MutableState` used to refer to one that encapsulates mutable state but not identity, a copy of a `MutableState>>` should hold a reference to a new list with references to the same objects; a copy of a `MutableState>>` should hold a reference to a a new list with copies of the items therein. – supercat Sep 24 '13 at 17:22
  • At first glance, it seems like an overly complex solution to a corner-case issue. Instead, implementing objects to support serialization would ensure that serializing/deserializing objects can be used to clone them and then the designer of each object is in control of what cloning means to them. – Jeff Yates Sep 24 '13 at 18:07
  • 1
    I just needed to be reminded of the first line - so I much prefer this answer, thanks @JeffYates! – Ian Grainger May 02 '14 at 11:20
  • I agree with @phoog, but If you think `AddRange` with Linq is less readable, then why not just use `foreach`. `ForEach` [_is harder to understand, harder to debug, and introduces closure semantics_](http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx) – juharr Sep 10 '15 at 13:12
  • I think the follow-on to @supercat is that your current taxonomy has a hole. You have value types & reference types you might mutate, but not reference types where shallow copies are appropriate. Perhaps: "*If your elements are value types* **[or are reference types where you're only worried list *membership*]**, *then you can just do [the shallow clone constructor]*". With reference types, you may want to edit the membership of `newList` w/o affecting membership of `oldList`, though you want edits to elements shared. **TL;DR:** Maybe make shallow vs. deep use cases w/ ref types explicit. – ruffin Mar 17 '18 at 14:32
457

You can use an extension method.

static class Extensions
{
    public static IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable
    {
        return listToClone.Select(item => (T)item.Clone()).ToList();
    }
}
nawfal
  • 70,104
  • 56
  • 326
  • 368
ajm
  • 4,732
  • 1
  • 16
  • 7
  • 77
    I think List.ConvertAll might do this in faster time, since it can pre-allocate the entire array for the list, versus having to resize all the time. – MichaelGG Oct 21 '08 at 17:43
  • 2
    @MichaelGG, what if you don't want to Convert but just Clone/Duplicate the items in the list? Would this work? || var clonedList = ListOfStrings.ConvertAll(p => p); – IbrarMumtaz Aug 17 '14 at 15:42
  • 32
    @IbrarMumtaz: That is the same as var clonedList = new List(ListOfStrings); – Brandon Arnold Sep 16 '14 at 14:00
  • 4
    Nice solution! By the way I prefer public static List CLone... It is more useful in the cases like this, because no further cast needed: List cloned = listToClone.Clone(); – Plutoz May 15 '15 at 07:02
  • @BrandonArnold you are wrong, what if T is an object, not value type? – Brian Ogden Aug 08 '16 at 02:34
  • @BrianOgden Isn't the ConvertAll delegate in his example also retaining reference types? The arrow function would need a copy constructor or cloning serializer (e.g. p => new PType(p)). – Brandon Arnold Aug 08 '16 at 02:45
  • Sorry @BrandonArnold you right, I thought your comment was in reference to the answer, you commenting on a comment from IbrarMumtaz, my bad, carry on as you were :) – Brian Ogden Aug 08 '16 at 15:01
  • 7
    Isn't this just half the answer since it relies on an implementation of ICloneable, which would be the important part of the question? – Everts Dec 16 '19 at 07:19
  • I agree it is only half the answer as it is missing the IClonable part. – AH. Mar 01 '21 at 12:55
  • I am surprised, no one has mentioned the issue that models must implement ICloneable and IClonable.Clone() returns type object, and so takes a boxing performance hit. – RBZ Nov 17 '21 at 18:47
111

For a shallow copy, you can instead use the GetRange method of the generic List class.

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

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

Quoted from: Generics Recipes

Jochem
  • 25
  • 7
Anthony Potts
  • 8,842
  • 8
  • 41
  • 56
  • 63
    You can also achieve this by using the List's contructor to specify a List from which to copy from. eg var shallowClonedList = new List(originalList); – Arkiliknam Feb 16 '12 at 14:58
  • 13
    I often use `List newList = oldList.ToList()`. Same effect. However, Arkiliknam's solution is best for readability in my opinion. – Dan Bechard Oct 25 '12 at 18:27
  • 2
    @DanBechard Years later, but I prefer `ToList` as it avoids all the redundancies - I wonder which is actually more performant... looked it up. Looks list `ToList` calls `new List` which ultimately will use `Array.CopyTo`, so about the same. – NetMage Nov 20 '20 at 18:59
95
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;
}

This is one way to do it with C# and .NET 2.0. Your object requires to be [Serializable()]. The goal is to lose all references and build new ones.

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
Patrick Desjardins
  • 136,852
  • 88
  • 292
  • 341
  • 15
    +1 - i like this answer - it is quick, dirty, nasty and very effective. I used in silverlight, and used the DataContractSerializer as the BinarySerializer was not available. Who needs to write pages of object cloning code when you can just do this? :) – slugster Mar 02 '10 at 11:52
  • 3
    I like this. While it's nice to do things "right", quick and dirty often comes in handy. – Odrade Dec 15 '10 at 18:11
  • 3
    Quick! but: Why dirty? – raiserle Dec 12 '13 at 11:54
  • 2
    This deep clones and is fast and easy. Carefull on other suggestions on this page. I tried several and they don't deep clone. – RandallTo May 29 '15 at 03:14
  • I like nasty and dirty^^ It's like JSON.parse(JSON.stringify(obj)). Brilliant! – Roman Jun 17 '15 at 18:17
  • 2
    Only negative aspect, if you can call it that, is that your classes have to be marked Serializable for this to work. – Tuukka Haapaniemi Sep 04 '15 at 09:38
  • 1
    BinaryFormatter is obsoleted in .NET 7. – Palle Due Dec 13 '22 at 12:52
51

To clone a list just call .ToList(). This creates a shallow copy.

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 }
> 
Xavier John
  • 8,474
  • 3
  • 37
  • 51
  • 61
    A little warning this is a shallow copy ... This will create two list objects, but the objects inside will be the same. I.e. changing one property will change the same object / property in the original list. – Mark G Jan 02 '18 at 13:08
  • @MarkG this is safe as long as you are using value types. – Nour Sep 24 '22 at 13:36
24

After a slight modification you can also clone:

public static T DeepClone<T>(T obj)
{
    T objResult;
    using (MemoryStream ms = new MemoryStream())
    {
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(ms, obj);
        ms.Position = 0;
        objResult = (T)bf.Deserialize(ms);
    }
    return objResult;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ajith
  • 265
  • 2
  • 3
  • Do not forget the T should be serializable, otherwise you get System.Runtime.Serialization.SerializationException. – Bence Végert Nov 23 '17 at 11:28
  • Good answer. **One hint:** You could add `if (!obj.GetType().IsSerializable) return default(T);` as the first statement which prevents the exception. And if you change it to an extension method, you could even use the Elvis operator like **`var b = a?.DeepClone();`** (given `var a = new List() { "a", "b" };` for example). – Matt Feb 22 '18 at 14:53
  • BinaryFormatter is made obsolete in .NET 7. See [Deserialization risks in use of BinaryFormatter and related types](https://aka.ms/binaryformatter) – kkuilla Apr 11 '23 at 18:39
18

Unless you need an actual clone of every single object inside your List<T>, the best way to clone a list is to create a new list with the old list as the collection parameter.

List<T> myList = ...;
List<T> cloneOfMyList = new List<T>(myList);

Changes to myList such as insert or remove will not affect cloneOfMyList and vice versa.

The actual objects the two Lists contain are still the same however.

Jader Feijo
  • 1,209
  • 1
  • 10
  • 11
  • 1
    I agree with user49126, I'm seeing that it is a shallow copy and changes made to one list are reflected in the other list. – Seidleroni Nov 19 '15 at 15:30
  • 2
    @Seidleroni, you are wrong. The changes made to the list itens are afected on the other list, changes in the list itself are not. – Wellington Zanelli Apr 19 '16 at 17:53
  • 2
    This is shallow copy. – Elliot Chen Aug 05 '16 at 17:58
  • How is this a shallow copy? – mko Sep 27 '18 at 11:41
  • 3
    @WellingtonZanelli Just confirmed that removing an element from myList removes it from cloneOfMyList as well. – Nick Gallimore Dec 16 '19 at 22:13
  • @NickGallimore - If true, that would be a surprising bug in List implementation. The definition of a new list is that it contains the same items at the time of creation, but has its own "state". Each item has two references to it, but any operation on the list itself is supposed to be independent. – ToolmakerSteve Jul 28 '21 at 14:54
17

Use AutoMapper (or whatever mapping lib you prefer) to clone is simple and a lot maintainable.

Define your mapping:

Mapper.CreateMap<YourType, YourType>();

Do the magic:

YourTypeList.ConvertAll(Mapper.Map<YourType, YourType>);
Derek Liang
  • 1,142
  • 1
  • 15
  • 22
16

If you only care about value types...

And you know the type:

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

If you don't know the type before, you'll need a helper function:

List<T> Clone<T>(IEnumerable<T> oldList)
{
    return newList = new List<T>(oldList);
}

The just:

List<string> myNewList = Clone(myOldList);
Lucas B
  • 11,793
  • 5
  • 37
  • 50
James Curran
  • 101,701
  • 37
  • 181
  • 258
12

If you have already referenced Newtonsoft.Json in your project and your objects are serializeable you could always use:

List<T> newList = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(listToCopy))

Possibly not the most efficient way to do it, but unless you're doing it 100s of 1000s of times you may not even notice the speed difference.

ProfNimrod
  • 4,142
  • 2
  • 35
  • 54
  • 6
    It's not about the speed difference, it's about the readability. If I came to this line of code I would slap my head and wonder why they introducted a third-party library to serialize and then deserialize an object which I would have no idea why it's happening. Also, this wouldn't work for a model list with objects that have a circular structure. – Jonathon Cwik Feb 04 '15 at 16:41
  • 2
    This code worked excellently for me for deep cloning. The app is migrating document boilerplate from Dev to QA to Prod. Each object is a packet of several document template objects, and each document in turn is comprised of a list of paragraph objects. This code let me serialize the .NET "source" objects and immediately deserialize them to new "target" objects, which then get saved to a SQL database in a different environment. After tons of research, I found lots of stuff, much of which was too cumbersome, and decided to try this. This short and flexible approach was "just right"! – Developer63 Nov 07 '15 at 07:01
8

For a deep copy, ICloneable is the correct solution, but here's a similar approach to ICloneable using the constructor instead of the ICloneable interface.

public class Student
{
  public Student(Student student)
  {
    FirstName = student.FirstName;
    LastName = student.LastName;
  }

  public string FirstName { get; set; }
  public string LastName { get; set; }
}

// wherever you have the list
List<Student> students;

// and then where you want to make a copy
List<Student> copy = students.Select(s => new Student(s)).ToList();

you'll need the following library where you make the copy

using System.Linq

you could also use a for loop instead of System.Linq, but Linq makes it concise and clean. Likewise you could do as other answers have suggested and make extension methods, etc., but none of that is necessary.

ztorstri
  • 369
  • 6
  • 12
  • 1
    That's called a "copy constructor". It's a v error prone approach, whenever you add a new field to Student, you have to remember to add it to the copy constructor. The main idea behind "clone" is to avoid that problem. – kenno Dec 01 '19 at 13:36
  • 2
    Even with ICloneable, you have to have a "Clone" method on your class. Unless you use reflection (which you could also use in the above approach), that Clone method is going to look real similar to the copy constructor approach above, and will suffer from the same issue of having to update for new/changed fields. But that's saying "The class has to be updated when fields of the class change". Of course it does ;) – ztorstri Dec 04 '19 at 18:06
  • 1
    There is a SERIOUS LIMITATION with this approach. Consider `class StudentB : Student`. In a list of `Students`, some might be `StudentB`s. `new Student(s)` will do the wrong thing - it will create a `Student`, not a `StudentB`. `ICloneable` does not have this limitation. (assuming StudentB also implements ICloneable.) – ToolmakerSteve Jul 28 '21 at 15:29
5

There is no need to flag classes as Serializable and in our tests using the Newtonsoft JsonSerializer even faster than using BinaryFormatter. With extension methods usable on every object.

attention: private members are not cloned

Standard .NET JavascriptSerializer option:

public static T DeepCopy<T>(this T value)
{
    JavaScriptSerializer js = new JavaScriptSerializer();

    string json = js.Serialize(value);

    return js.Deserialize<T>(json);
}

Faster option using Newtonsoft JSON:

public static T DeepCopy<T>(this T value)
{
    string json = JsonConvert.SerializeObject(value);

    return JsonConvert.DeserializeObject<T>(json);
}
F.H.
  • 1,456
  • 1
  • 20
  • 34
  • 4
    Private members are not cloned using the JSON method. https://stackoverflow.com/a/78612/885627 – himanshupareek66 Nov 22 '17 at 15:08
  • Not sure if this helps anyone. In my case the JSON option was not working (exception: "System.InvalidCastException: Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type ...") but it worked when I changed the last line slightly, like this: public static T DeepCloneJSON(this T value) { string json = JsonConvert.SerializeObject(value); return (T)JsonConvert.DeserializeObject(json, value.GetType()); } – luiggig Jul 15 '22 at 17:06
4
 //try this
 List<string> ListCopy= new List<string>(OldList);
 //or try
 List<T> ListCopy=OldList.ToList();
Steve
  • 21
  • 4
4

I'll be lucky if anybody ever reads this... but in order to not return a list of type object in my Clone methods, I created an interface:

public interface IMyCloneable<T>
{
    T Clone();
}

Then I specified the extension:

public static List<T> Clone<T>(this List<T> listToClone) where T : IMyCloneable<T>
{
    return listToClone.Select(item => (T)item.Clone()).ToList();
}

And here is an implementation of the interface in my A/V marking software. I wanted to have my Clone() method return a list of VidMark (while the ICloneable interface wanted my method to return a list of object):

public class VidMark : IMyCloneable<VidMark>
{
    public long Beg { get; set; }
    public long End { get; set; }
    public string Desc { get; set; }
    public int Rank { get; set; } = 0;

    public VidMark Clone()
    {
        return (VidMark)this.MemberwiseClone();
    }
}

And finally, the usage of the extension inside a class:

private List<VidMark> _VidMarks;
private List<VidMark> _UndoVidMarks;

//Other methods instantiate and fill the lists

private void SetUndoVidMarks()
{
    _UndoVidMarks = _VidMarks.Clone();
}

Anybody like it? Any improvements?

John Kurtz
  • 775
  • 8
  • 16
3

If you need a cloned list with the same capacity, you can try this:

public static List<T> Clone<T>(this List<T> oldList)
{
    var newList = new List<T>(oldList.Capacity);
    newList.AddRange(oldList);
    return newList;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
3
    public List<TEntity> Clone<TEntity>(List<TEntity> o1List) where TEntity : class , new()
    {
        List<TEntity> retList = new List<TEntity>();
        try
        {
            Type sourceType = typeof(TEntity);
            foreach(var o1 in o1List)
            {
                TEntity o2 = new TEntity();
                foreach (PropertyInfo propInfo in (sourceType.GetProperties()))
                {
                    var val = propInfo.GetValue(o1, null);
                    propInfo.SetValue(o2, val);
                }
                retList.Add(o2);
            }
            return retList;
        }
        catch
        {
            return retList;
        }
    }
3
public static Object CloneType(Object objtype)
{
    Object lstfinal = new Object();

    using (MemoryStream memStream = new MemoryStream())
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
        binaryFormatter.Serialize(memStream, objtype); memStream.Seek(0, SeekOrigin.Begin);
        lstfinal = binaryFormatter.Deserialize(memStream);
    }

    return lstfinal;
}
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
pratik
  • 31
  • 1
3

If I need deep copy of collection, I have favorite approach like this:

public static IEnumerable<T> DeepCopy<T>(this IEnumerable<T> collectionToDeepCopy)
{
    var serializedCollection = JsonConvert.SerializeObject(collectionToDeepCopy);
    return JsonConvert.DeserializeObject<IEnumerable<T>>(serializedCollection);
}
Martin Zaloga
  • 127
  • 1
  • 10
  • Serializing data to text is very resource expensive compared to the actual job that needs to be done. This can be ok if you are not working on production code tho, just a one-time thing. – Preza8 Feb 12 '22 at 20:30
3
public class CloneableList<T> : List<T>, ICloneable where T : ICloneable
{
  public object Clone()
  {
    var clone = new List<T>();
    ForEach(item => clone.Add((T)item.Clone()));
    return clone;
  }
}
Peter
  • 155
  • 2
  • 9
2

You can use extension method:

namespace extension
{
    public class ext
    {
        public static List<double> clone(this List<double> t)
        {
            List<double> kop = new List<double>();
            int x;
            for (x = 0; x < t.Count; x++)
            {
                kop.Add(t[x]);
            }
            return kop;
        }
   };

}

You can clone all objects by using their value type members for example, consider this class:

public class matrix
{
    public List<List<double>> mat;
    public int rows,cols;
    public matrix clone()
    { 
        // create new object
        matrix copy = new matrix();
        // firstly I can directly copy rows and cols because they are value types
        copy.rows = this.rows;  
        copy.cols = this.cols;
        // but now I can no t directly copy mat because it is not value type so
        int x;
        // I assume I have clone method for List<double>
        for(x=0;x<this.mat.count;x++)
        {
            copy.mat.Add(this.mat[x].clone());
        }
        // then mat is cloned
        return copy; // and copy of original is returned 
    }
};

Note: if you do any change on copy (or clone) it will not affect the original object.

Athafoud
  • 2,898
  • 3
  • 40
  • 58
Furkan Katı
  • 51
  • 1
  • 8
  • This is a very basic example that has no use in real world programming. You have to clone a list of complex objects with children of lists of other objects and so on. – Alexandru Dicu Oct 27 '21 at 19:53
2

Using a cast may be helpful, in this case, for a shallow copy:

IList CloneList(IList list)
{
    IList result;
    result = (IList)Activator.CreateInstance(list.GetType());
    foreach (object item in list) result.Add(item);
    return result;
}

applied to generic list:

List<T> Clone<T>(List<T> argument) => (List<T>)CloneList(argument);
1

I use automapper to copy an object. I just setup a mapping that maps one object to itself. You can wrap this operation any way you like.

http://automapper.codeplex.com/

Dan H
  • 1,828
  • 2
  • 21
  • 38
0

I've made for my own some extension which converts ICollection of items that not implement IClonable

static class CollectionExtensions
{
    public static ICollection<T> Clone<T>(this ICollection<T> listToClone)
    {
        var array = new T[listToClone.Count];
        listToClone.CopyTo(array,0);
        return array.ToList();
    }
}
Kamil Budziewski
  • 22,699
  • 14
  • 85
  • 105
  • seems some collections (e.g. DataGrid's SelectedItems at Silverlight) skip the implementation of CopyTo which is a problem with this approach – George Birbilis Jun 14 '15 at 13:35
0

You could also simply convert the list to an array using ToArray, and then clone the array using Array.Clone(...). Depending on your needs, the methods included in the Array class could meet your needs.

Avi
  • 21,182
  • 26
  • 82
  • 121
JHaps
  • 41
  • 3
  • This does not work; changes to the values in the cloned array STILL change the values in the original list. – Bernoulli Lizard Feb 02 '17 at 15:34
  • you can use var clonedList = ListOfStrings.ConvertAll(p => p); as given by @IbrarMumtaz .... Works effectively... Changes to one list are kept to itself and doesn't to reflect in another – zainul Feb 13 '17 at 07:01
0

The following code should transfer onto a list with minimal changes.

Basically it works by inserting a new random number from a greater range with each successive loop. If there exist numbers already that are the same or higher than it, shift those random numbers up one so they transfer into the new larger range of random indexes.

// Example Usage
int[] indexes = getRandomUniqueIndexArray(selectFrom.Length, toSet.Length);

for(int i = 0; i < toSet.Length; i++)
    toSet[i] = selectFrom[indexes[i]];


private int[] getRandomUniqueIndexArray(int length, int count)
{
    if(count > length || count < 1 || length < 1)
        return new int[0];

    int[] toReturn = new int[count];
    if(count == length)
    {
        for(int i = 0; i < toReturn.Length; i++) toReturn[i] = i;
        return toReturn;
    }

    Random r = new Random();
    int startPos = count - 1;
    for(int i = startPos; i >= 0; i--)
    {
        int index = r.Next(length - i);
        for(int j = startPos; j > i; j--)
            if(toReturn[j] >= index)
                toReturn[j]++;
        toReturn[i] = index;
    }

    return toReturn;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

Another thing: you could use reflection. If you'll cache this properly, then it'll clone 1,000,000 objects in 5.6 seconds (sadly, 16.4 seconds with inner objects).

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Person
{
       ...
      Job JobDescription
       ...
}

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Job
{...
}

private static readonly Type stringType = typeof (string);

public static class CopyFactory
{
    static readonly Dictionary<Type, PropertyInfo[]> ProperyList = new Dictionary<Type, PropertyInfo[]>();

    private static readonly MethodInfo CreateCopyReflectionMethod;

    static CopyFactory()
    {
        CreateCopyReflectionMethod = typeof(CopyFactory).GetMethod("CreateCopyReflection", BindingFlags.Static | BindingFlags.Public);
    }

    public static T CreateCopyReflection<T>(T source) where T : new()
    {
        var copyInstance = new T();
        var sourceType = typeof(T);

        PropertyInfo[] propList;
        if (ProperyList.ContainsKey(sourceType))
            propList = ProperyList[sourceType];
        else
        {
            propList = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            ProperyList.Add(sourceType, propList);
        }

        foreach (var prop in propList)
        {
            var value = prop.GetValue(source, null);
            prop.SetValue(copyInstance,
                value != null && prop.PropertyType.IsClass && prop.PropertyType != stringType ? CreateCopyReflectionMethod.MakeGenericMethod(prop.PropertyType).Invoke(null, new object[] { value }) : value, null);
        }

        return copyInstance;
    }

I measured it in a simple way, by using the Watcher class.

 var person = new Person
 {
     ...
 };

 for (var i = 0; i < 1000000; i++)
 {
    personList.Add(person);
 }
 var watcher = new Stopwatch();
 watcher.Start();
 var copylist = personList.Select(CopyFactory.CreateCopyReflection).ToList();
 watcher.Stop();
 var elapsed = watcher.Elapsed;

RESULT: With inner object PersonInstance - 16.4, PersonInstance = null - 5.6

CopyFactory is just my test class where I have dozen of tests including usage of expression. You could implement this in another form in an extension or whatever. Don't forget about caching.

I didn't test serializing yet, but I doubt in an improvement with a million classes. I'll try something fast protobuf/newton.

P.S.: for the sake of reading simplicity, I only used auto-property here. I could update with FieldInfo, or you should easily implement this by your own.

I recently tested the Protocol Buffers serializer with the DeepClone function out of the box. It wins with 4.2 seconds on a million simple objects, but when it comes to inner objects, it wins with the result 7.4 seconds.

Serializer.DeepClone(personList);

SUMMARY: If you don't have access to the classes, then this will help. Otherwise it depends on the count of the objects. I think you could use reflection up to 10,000 objects (maybe a bit less), but for more than this the Protocol Buffers serializer will perform better.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Roma Borodov
  • 596
  • 4
  • 10
0

There is a simple way to clone objects in C# using a JSON serializer and deserializer.

You can create an extension class:

using Newtonsoft.Json;

static class typeExtensions
{
    [Extension()]
    public static T jsonCloneObject<T>(T source)
    {
    string json = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(json);
    }
}

To clone and object:

obj clonedObj = originalObj.jsonCloneObject;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

For a deep clone I use reflection as follows:

public List<T> CloneList<T>(IEnumerable<T> listToClone) {
    Type listType = listToClone.GetType();
    Type elementType = listType.GetGenericArguments()[0];
    List<T> listCopy = new List<T>();
    foreach (T item in listToClone) {
        object itemCopy = Activator.CreateInstance(elementType);
        foreach (PropertyInfo property in elementType.GetProperties()) {
            elementType.GetProperty(property.Name).SetValue(itemCopy, property.GetValue(item));
        }
        listCopy.Add((T)itemCopy);
    }
    return listCopy;
}

You can use List or IEnumerable interchangeably.

Zeyad
  • 537
  • 2
  • 7
  • 15
0

You can use the List<T>.ConvertAll(Converter<T, T>) method to create a new list containing all the elements of the original list, and use a conversion function that returns the input value.

List<int> originalList = new List<int> { 1, 2, 3, 4, 5 };
List<int> clonedList = new List<int>(originalList.ConvertAll(x => x));
Imraan
  • 96
  • 9