By Fiona


2008-10-21 16:47:05 8 Comments

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?

26 comments

@Xavier John 2017-09-25 00:35:03

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 }
> 

@curveorzos 2017-11-14 22:20:50

Simplest solution by far

@Mark G 2018-01-02 13:08:57

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.

@ztorstri 2019-05-13 21:04:01

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.

@kenno 2019-12-01 13:36:21

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.

@ztorstri 2019-12-04 18:06:04

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 ;)

@Thomas Cerny 2019-02-27 09:51:41

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);

@John Kurtz 2019-01-21 17:15:02

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?

@Anthony Potts 2008-10-21 16:52:10

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

@Arkiliknam 2012-02-16 14:58:25

You can also achieve this by using the List<T>'s contructor to specify a List<T> from which to copy from. eg var shallowClonedList = new List<MyObject>(originalList);

@Dan Bechard 2012-10-25 18:27:06

I often use List<int> newList = oldList.ToList(). Same effect. However, Arkiliknam's solution is best for readability in my opinion.

@hamzeh.hanandeh 2020-06-21 12:51:37

That's working, thank you

@Steve 2018-02-18 04:52:43

 //try this
 List<string> ListCopy= new List<string>(OldList);
 //or try
 List<T> ListCopy=OldList.ToList();

@Albert arnau 2017-01-20 08:43:49

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;

@F.H. 2016-11-09 13:55:33

My friend Gregor Martinovic and I came up with this easy solution using a JavaScript Serializer. 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.

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);
}

@himanshupareek66 2017-11-22 15:08:04

Private members are not cloned using the JSON method. stackoverflow.com/a/78612/885627

@user3245269 2015-12-22 02:19:04

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;
}

@Roma Borodov 2015-12-18 23:56:44

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.

@Adam Lewis 2015-09-03 11:23:03

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;
}

@Furkan Katı 2013-06-07 11:37:58

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.

@shahrooz.bazrafshan 2016-04-10 07:40:51

    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;
        }
    }

@Jader Feijo 2015-07-10 14:09:54

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.

@Seidleroni 2015-11-19 15:30:16

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.

@Wellington Zanelli 2016-04-19 17:53:22

@Seidleroni, you are wrong. The changes made to the list itens are afected on the other list, changes in the list itself are not.

@Elliot Chen 2016-08-05 17:58:14

This is shallow copy.

@mko 2018-09-27 11:41:31

How is this a shallow copy?

@Nick Gallimore 2019-12-16 22:13:18

@WellingtonZanelli Just confirmed that removing an element from myList removes it from cloneOfMyList as well.

@Patrick Desjardins 2008-10-21 17:43:34

public static object DeepClone(object obj) 
{
  object objResult = null;
  using (MemoryStream  ms = new MemoryStream())
  {
    BinaryFormatter  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.

@slugster 2010-03-02 11:52:55

+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? :)

@Odrade 2010-12-15 18:11:28

I like this. While it's nice to do things "right", quick and dirty often comes in handy.

@raiserle 2013-12-12 11:54:02

Quick! but: Why dirty?

@RandallTo 2015-05-29 03:14:51

This deep clones and is fast and easy. Carefull on other suggestions on this page. I tried several and they don't deep clone.

@Roman 2015-06-17 18:17:21

I like nasty and dirty^^ It's like JSON.parse(JSON.stringify(obj)). Brilliant!

@Tuukka Haapaniemi 2015-09-04 09:38:29

Only negative aspect, if you can call it that, is that your classes have to be marked Serializable for this to work.

@JHaps 2015-01-15 15:08:20

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.

@Bernoulli Lizard 2017-02-02 15:34:33

This does not work; changes to the values in the cloned array STILL change the values in the original list.

@zainul 2017-02-13 07:01:05

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

@Dan H 2014-10-13 14:28:08

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/

@ProfNimrod 2013-11-01 14:43:56

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.

@Jonathon Cwik 2015-02-04 16:41:30

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.

@Developer63 2015-11-07 07:01:18

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"!

@ajm 2008-10-21 16:58:54

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();
    }
}

@MichaelGG 2008-10-21 17:43:09

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.

@IbrarMumtaz 2014-08-17 15:42:46

@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);

@Brandon Arnold 2014-09-16 14:00:29

@IbrarMumtaz: That is the same as var clonedList = new List<string>(ListOfStrings);

@Plutoz 2015-05-15 07:02:06

Nice solution! By the way I prefer public static List<T> CLone<T>... It is more useful in the cases like this, because no further cast needed: List<MyType> cloned = listToClone.Clone();

@George Birbilis 2015-06-14 13:34:25

this is deep cloning

@Brian Ogden 2016-08-08 02:34:30

@BrandonArnold you are wrong, what if T is an object, not value type?

@Brandon Arnold 2016-08-08 02:45:44

@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)).

@Brian Ogden 2016-08-08 15:01:14

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 :)

@Everts 2019-12-16 07:19:10

Isn't this just half the answer since it relies on an implementation of ICloneable, which would be the important part of the question?

@Kamil Budziewski 2013-07-03 12:41:06

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();
    }
}

@George Birbilis 2015-06-14 13:35:45

seems some collections (e.g. DataGrid's SelectedItems at Silverlight) skip the implementation of CopyTo which is a problem with this approach

@James Curran 2008-10-21 16:54:41

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);

@Jeff Yates 2008-10-21 16:57:47

This doesn't clone the elements.

@Derek Liang 2013-02-13 23:20:22

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>);

@Ajith 2011-07-20 09:26:17

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;
}

@Bence Végert 2017-11-23 11:28:02

Do not forget the T should be serializable, otherwise you get System.Runtime.Serialization.SerializationException.

@Matt 2018-02-22 14:53:43

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<string>() { "a", "b" }; for example).

@Peter 2011-10-07 07:04:00

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;
  }
}

@pratik 2011-04-25 12:18:33

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;
}

@Jeff Yates 2008-10-21 16:54:15

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).

@MichaelGG 2008-10-21 17:42:25

I think List<T>.ConvertAll might look nicer than creating a new list and doing a foreach+add.

@Jeff Yates 2008-10-22 15:57:21

Good point. I must admit, I'm still coming to grips with all the LINQ calls myself.

@Dimitri C. 2010-09-09 10:12:21

+1 So in summary, it is impossible to provide a deep clone function for a Generic.List. Is that right?

@Jeff Yates 2010-09-10 14:36:10

@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<T>, you will have to do it without ICloneable to be sure it is a deep copy.

@phoog 2010-12-21 16:00:35

Why not use the AddRange method? (newList.AddRange(oldList.Select(i => i.Clone()) or newList.AddRange(oldList.Select(i => new YourType(i))

@Jeff Yates 2010-12-21 18:04:43

@phoog: It's another option, sure. It doesn't make much difference.

@phoog 2010-12-21 19:43:15

@Jeff Yates: It does make a difference if the collection argument to AddRange implements ICollection<T>. 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.

@Jeff Yates 2010-12-21 20:36:25

@phoog: That's an optimization I'd avoid unless it was clear from profiling that it was needed.

@phoog 2010-12-21 22:37:11

@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.

@Jeff Yates 2010-12-22 15:18:51

@phoog: I think that it is a little less readable/understandable when scanning the code, that's all. Readability wins for me.

@markmnl 2011-05-30 04:21:03

why not use ToArray() - that does create a deep copy - it uses memmove effectively

@Jeff Yates 2011-05-30 19:46:11

@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.

@markmnl 2011-05-31 01:08:57

yes, of course you are right, sorry, it is very unlikely the class only consists of value types

@supercat 2013-09-23 21:25:13

@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.

@Jeff Yates 2013-09-24 15:54:24

@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.

@supercat 2013-09-24 17:06:59

@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 2013-09-24 17:22:15

If an Identity<T> was regarded as a reference to a T used to encapsulate identity only, and a MutableState<T> used to refer to one that encapsulates mutable state but not identity, a copy of a MutableState<List<Identity<T>>> should hold a reference to a new list with references to the same objects; a copy of a MutableState<List<MutableState<T>>> should hold a reference to a a new list with copies of the items therein.

@Jeff Yates 2013-09-24 18:07:29

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.

@Ian Grainger 2014-05-02 11:20:57

I just needed to be reminded of the first line - so I much prefer this answer, thanks @JeffYates!

@juharr 2015-09-10 13:12:15

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

@ruffin 2018-03-17 14:32:35

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.

Related Questions

Sponsored Content

21 Answered Questions

69 Answered Questions

[SOLVED] How do I correctly clone a JavaScript object?

62 Answered Questions

[SOLVED] How do you split a list into evenly sized chunks?

48 Answered Questions

[SOLVED] Deep cloning objects

  • 2008-09-17 00:06:27
  • NakedBrunch
  • 815274 View
  • 2247 Score
  • 48 Answer
  • Tags:   c# .net clone

40 Answered Questions

[SOLVED] How to make a flat list out of list of lists?

20 Answered Questions

[SOLVED] How to Sort a List<T> by a property in the object

27 Answered Questions

[SOLVED] How do I check if a list is empty?

  • 2008-09-10 06:20:11
  • Ray
  • 2939831 View
  • 3234 Score
  • 27 Answer
  • Tags:   python list

14 Answered Questions

[SOLVED] How to randomly select an item from a list?

  • 2008-11-20 18:42:21
  • Ray
  • 1420460 View
  • 1785 Score
  • 14 Answer
  • Tags:   python list random

64 Answered Questions

[SOLVED] What is the difference between String and string in C#?

67 Answered Questions

[SOLVED] What is the most efficient way to deep clone an object in JavaScript?

Sponsored Content