I wish to make a copy of a list, where the elements of the list are also copied, instead of just the references, so I can then change them without affecting the original elements.
It seems a very simple thing, it should be like:
MySecondList = MyFirstList.CopyAll();
but I cannot find it. Come to think of it, I don't know how to copy the elements one by one either if they aren't simple types. Strange, I never needed to do this before.
Help is appreciated,
Guido

How to make a copy of a list?
RajuK
No, that doesn't help me because the elements are still references to the same instances as in the old list.
Further, this roundabout way is far more cumbersome than using a constructor.
Duck4565654
But if they were still references to the same instances as in the old list wouldn't the output be:
Output:
origional: -1 modified: -1
origional: 0 modified: 0
origional: 1 modified: 1
origional: 2 modified: 2
origional: 3 modified: 3
origional: 4 modified: 4
origional: 5 modified: 5
origional: 6 modified: 6
origional: 7 modified: 7
origional: 8 modified: 8
But it is not! We updated the items in the copied list and not the items in the origional therefore the items in copied list are pointing to a different location than that of the origional list.
I'm not sure about the objects within each item of the list, but each of those items are pointing to a new location in memory than the items in the origional list.
Andres Aguiar
Guido,
I believe the prefered way to copy any array is using the Array.Copy(...) method. When dealing with an array you can use the List<>'s ToArray() method to make a copy of your list.
public static List<int> Copy(List<int> origList){
int[] newIntArray = new int[origList.Count];
Array.Copy(
origList.ToArray(),
newIntArray,
origList.Count); return new List<int>(newIntArray);
}
Example:
static
void Main(string[] args){
List<int> integerList = new List<int>();
for (int i = 0; i < 10; i++)
{
integerList.Add(i);
}
List<int> newIntegerList = Copy(integerList);
for (int i = 0; i < integerList.Count; i++)
{
newIntegerList
Console.WriteLine("origional: {0} modified: {1}",
integerList
newIntegerList
}
}
Output:
origional: 0 modified: -1
origional: 1 modified: 0
origional: 2 modified: 1
origional: 3 modified: 2
origional: 4 modified: 3
origional: 5 modified: 4
origional: 6 modified: 5
origional: 7 modified: 6
origional: 8 modified: 7
origional: 9 modified: 8
Hope this helps!
tpiazza55
OK, I am using a constructor now for both the element class and the list class:
public MyList(MyList myToCopyList){
foreach (MyElement myToCopyElement in myToCopyList) Add(new MyElement(myToCopyElement)); }This works and looks relatively neat, but of course the extra constructor for MyElement is quite ugly.
janderson
Well, the syntax should take care of that.
For instance:
myNewList=myOldList.Copy();
copies the elements as references,
myNewList=myOldList.Copy(myElement);
deep-copies the myElements but not any class instances within them, and
myNewList=myOldList.Copy(myElement.Copy(mySecondClassInstance, myFifthClassInstance))
also deep-copies my second and fifth class instances inside the elements, etc.
Or something like this, and where the Copy method can be overridden when needed.
m.mirzakhah
I don't think I understand what your suggesting with that code sample. How does the argument tell the list when to make a new copy of an object and when just to copy the reference
In any case, what I was suggesting was to write a function like this:
While the ICloneable interface does have certain difficiencies, this implementation has the advantage that it can copy any list where its element type implements the ICloneable interface. So, it can be reused for lists of various types, as long as the list's element type implements the ICloneable.Clone method.
Julio Parra
- Scaling behaviour: Shallow copies scale as O(n) - e.g. linearly - where n is the number of elements in an array or fields in a class/struct. The scaling behaviour of deep copies depends on the structure of your classes/structs.
- Reference cycles: Let's say A references B and C. B also references C. If you deep copy A, do you want two copies of C or one Chances are only one, but that's for your deep copy algorithm to decide.
- Deep or shallow on dependent objects: Although you might want to deep copy the collection, objects referenced by object in the collection might better be shallow copied. For instance, let's say you have a collection of orders, which reference a customer. Although you want to take a copy of the orders, the referenced customer objects might need to reference the same customer object as the original.
So the semantics of a deep copy are highly application and/or class/struct dependent.A good (and short) discussion of ICloneable can be found here:
http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=373454&SiteID=1
Basically there are a few design problems with ICloneable, notably the fact that it doesn't specify whether a deep or shallow copy is performed and that it is type-unsafe. (Clone returns an object, which must then be cast to a specific type.) The preferred implementation technique is using copy constructors - a constructor that takes a reference to an object of the same type.
Hopefully this helps rationalize why deep copy isn't built into the Framework.
Cush
bvautier
Unfortunately, there is no automated way to do this, as far as I know. I assume that your list contains objects of classes that you created. If this is the case, then probably the best answer is to have them implement the ICloneable interface so that you can use the Clone method to make the copies for your second list. When implementing the Clone method, it may be usefull to use the MemberwiseClone method, but be warned that this makes only a shallow copy.
I hope this points you in the right direction. If you have any more questions, please ask.
SJVCT
Shallow means that it only copies the references, right
I don't see how that solves anything then, as I would still have to copy every single bit of my elements explicitly (so I might as well write a copy method for them instead of using an interface).