How do I really copy a List<T> object?

OK, color me annoyed. I want to copy a List<T> object because I want to manipulate the junk in it. The junk is in the ASP.NET cache, so if I alter it, it gets changed and the change is reflected on the next request.

For example... right now I have

List<Foo> list = Foo.GetFromCache();
list[0].MyString = "yo";


As you would expect, that MyString property is going to be "yo" next time I get it. I tried using List<T>.CopyTo() to copy it to an array, but that array is still a reference to the original.

It's gotta be easier... right?

13 Comments

  • I guess the same way you do an ArrayList, serialize the object and then deserialize it, try:



    BinaryFormatter bf = new BinaryFormatter();

    MemoryStream ms = new MemoryStream();



    bf.Serialize(ms, strings);

    ms.Seek(0, SeekOrigin.Begin);

    List&lt;string&gt; copy = (List&lt;string&gt;)bf.Deserialize(ms) ;

    ms.Close();



    Karl

  • You have to either serialize then deserialize, or manually call ICloneable.Clone on each element as you construct a new List. Depending on the types involved, one may be faster than the other.



    In either case, if the type Foo isn't marked with the SerializableAttribute or it doesn't implement ICloneable (and you don't own Foo so can't implement it yourself), then you're pretty screwed, I would think...

  • Is there some good reason for this omission from the framework? My Java buddy was telling me you can call a Copy() method on practically anything to do this.

  • Well, I guess it's the same reason that they require you to implement ICloneable yourself rather than doing it automatically. Technically, there's no reason why they couldn't have included a 'Deep-copy' directly into the framework, but they decided to make it manual.



    Also, you could write your own List which supported a deep-copy clone, something like this:



    class CloneableList&lt;T : ICloneable&gt; : List&lt;T&gt;, ICloneable

    {

    public object Clone()

    {

    CloneableList&lt;T&gt; clone = new CloneableList&lt;T&gt;(this.Count);

    foreach(T t in this)

    {

    clone.Add(((ICloneable) t).Clone());

    }

    return clone;

    }

    }



    That's just off the top of my head, so I might have got something wrong, but that's the basic idea...

  • ... and in the object to clone, call base.MemberwiseClone() to get a deep copy.

  • Or you may use something like:

    yourList.ForEach(delegate(string s) { yourListTwo.Add(s); });

  • Could try this one to make a real copy of a list-object.

    List list_1= Common.FillMyListWithMyTypeObjects();
    List list_2 = new List();
    list.InsertRange(0, list_1);

    So you don't have a object which is linked to the same refernce, it's a complete new object!

    Hope that works

  • Very useful post about using serialization for cloning objects

  • what about

    l1.Categories.ForEach(l2.Add);

  • Check for overloaded constructors for List. One of them accepts IEnumerable(T) as parameter and copies the content of this list to another.

    //Original List
    List orgList = new List();
    ...

    //New List
    List newList = new List(orgList);

    Hope I am correct. This is my first reply to any blog!!!

  • The problem with using

    List newList = new List(orgList);

    Is that it works only when T is a value type such as int, bool, and so on, it does not work with reference types. You just have a new list that contains the SAME references as the old list and if you change any property of one of the list objects, it will change in BOTH lists. In the end, you just have to create NEW objects of type T, do a deep copy of the object and add it to a new list.

    Rob

  • "Or you may use something like:

    yourList.ForEach(delegate(string s) { yourListTwo.Add(s); });"

    didnt work either...

    im trying to clono an object lista, but any change apply to the new one, affects the old one...

    is there any solution for framework 2.0??

  • l1 = l2.ToList()

Comments have been disabled for this content.