3

I know this has been covered before but from what I understand in the post this should work.

Example code:

I have a custom type:

public class MyType
{
    public List<MySubType> Movie { get; set; }
    public List<int> Ranks { get; set; }
    public string Location { get; set; }
    public string Released { get; set; }
}

I then create a List of this type

List<MyType> myMovies = new List<MyType>();

Later in the code I need to create a copy of this list and change it without affecting the original.

List<MyType> copyMovies = new List<MyType>(myMovies);

But now if I remove from the list within copyMovies

copyMovies.Movie.RemoveAt(x);

It removes from both lists

Unless I am totally missing something this post suggests I should be able to change the copy list without it effecting the original.

Community
  • 1
  • 1
Fred
  • 5,663
  • 4
  • 45
  • 74
  • Have you tried to clone the list? like here http://stackoverflow.com/questions/222598/how-do-i-clone-a-generic-list-in-c – Shachaf.Gortler Apr 24 '14 at 11:36
  • 8
    That's not true. If you remove from the second it will not be removed from the first. – Tim Schmelter Apr 24 '14 at 11:37
  • 6
    Your code should work. `new List(myMovies)` should create a new list containing the same items. Your problem seems to be external to the question. – Avish Apr 24 '14 at 11:37
  • Look at the 2nd answer for more information: http://stackoverflow.com/questions/222598/how-do-i-clone-a-generic-list-in-c – Stormenet Apr 24 '14 at 11:37
  • 1
    Are u sure ? You really tested the RemoveAt? – Only a Curious Mind Apr 24 '14 at 11:38
  • @TimSchmelter Maybe it shouldn't but it is. – Fred Apr 24 '14 at 11:39
  • 1
    If so, I believe at some stage you do this `copyMovies = myMovies;` – Sriram Sakthivel Apr 24 '14 at 11:40
  • @LucasAbilidebob Yes many times – Fred Apr 24 '14 at 11:41
  • @SriramSakthivel No nowhere in the code do I do that. – Fred Apr 24 '14 at 11:42
  • So you're saying that one list's `RemoveAt()` method is deleting items of another list? That is physically impossible unless both lists are referencing the same list object. – Tarec Apr 24 '14 at 11:42
  • Nope, If you need more help you need to provide a short but complete sample which reproduces the problem! – Sriram Sakthivel Apr 24 '14 at 11:43
  • @Tarec I have just checked, rechecked and triple rechecked the code and that is exactly what is happening. – Fred Apr 24 '14 at 11:45
  • 1
    @Fred I've tested your implementation, and it works fine. Please, execute your test again. – Only a Curious Mind Apr 24 '14 at 11:46
  • And the downvote was for what exactly? Or the close vote come to that!! – Fred Apr 24 '14 at 11:47
  • @Fred The downvote is because your implementation works fine, you didn't validate correctly before open a question. – Only a Curious Mind Apr 24 '14 at 11:50
  • @Fred For writing nonsense. The code you provided IS NOT generating the problem you're describing. You refuse to show us the rest of your code, thus your questions is pointless. – Tarec Apr 24 '14 at 11:50
  • @Tarec Ok slightly misleading. I am removing from the List within the List (question updated). But it IS generating the problem I explain. – Fred Apr 24 '14 at 11:58
  • @Fred: See my updated answer. Your example was wrong. – Patrick Hofman Apr 24 '14 at 12:04
  • @Fred: now your code wouldn't even compile because a `List` has no `Movie` property. Maybe something like `copyMovies[0].Movie.RemoveAt` but then you should show your real code. – Tim Schmelter Apr 24 '14 at 13:06
  • @TimSchmelter good point well made. Bit of a moot point now but the original code... `surveyCollectionToUpload[s].Surveys.RemoveAt(i);` I just missed a vital bit out of my question probably due to tiredness. I am now doing a deep clone using DataContractSerializer. I think the firing squad will be round for me at 8! – Fred Apr 24 '14 at 13:25

3 Answers3

16

You can simply call ToList() on your original list, and it will generate a copy.

Scott
  • 17,127
  • 5
  • 53
  • 64
3

I am pretty sure your code should work. MSDN says about the constructor:

Initializes a new instance of the List class that contains elements copied from the specified collection and has sufficient capacity to accommodate the number of elements copied.

Are you sure you didn't miss anything?

EDIT:

You did miss something... Your example was wrong and misleading. Your edit showed you try to delete an item from the list INSIDE your type. These are not copied / cloned when copying the parent class. You need to Clone each and every single property of your class. Take a look at Deep cloning objects.

Community
  • 1
  • 1
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • Yes I did miss something and I apologize unreservedly to the SO community for the obvious destress caused. Thanks for your link. – Fred Apr 24 '14 at 12:24
  • @Fred: No problem. Usually people know here where they are talking about, so don't keep saying it doesn't work and you tested it, while it doesn't. But in the end, we have all been there. – Patrick Hofman Apr 24 '14 at 12:25
2

Well if you think that copyMovies.RemoveAt(x) instead of copyMovies.Movie.RemoveAt(x) is only SLIGHTLY MISLEADING then sorry my friend, but you're just wasting our time here.

Internal list has been copied by a reference, so you need to copy the whole internal list instead, f.e:

List<MyType> copyMovies = new List<MyType>(myMovies.Select (m => new MyType()
{
    Movie = new List<MySubType>(m.Movie),
    Ranks = m.Ranks,
    Location = m.Location,
    Released = m.Released
}));

or

List<MyType> copyMovies = myMovies.Select (m => new MyType()
{
    Movie = new List<MySubType>(m.Movie),
    Ranks = m.Ranks,
    Location = m.Location,
    Released = m.Released
}).ToList();

Or with the copy constructor:

//in MyType definition
public MyType(MyType objectToCopy)
{
    Movie = new List<MySubType>(m.Movie);
    Ranks = m.Ranks;
    Location = m.Location;
    Released = m.Released;
}

and then you'd be able to use it this way:

List<MyType> copyMovies = myMovies.Select (m => new MyType(m));
Tarec
  • 3,268
  • 4
  • 30
  • 47
  • 28 hrs straight and I missed a bit of detail that, even now I understand to be the problem, still cannot see why a cloning the object would only clone part of it. Shoot me now why dont you! – Fred Apr 24 '14 at 12:21
  • 1
    @Fred: That is called: by design. What do you think happens when cloning objects with multiple, maybe even circular, references? How to determine what to clone and what not? – Patrick Hofman Apr 24 '14 at 12:26
  • @Fred No, whole list has been cloned. You need to realize the list does not hold reference-type objects, it only holds REFERENCES to them. ALL references has been cloned properly, they just have been pointing to the same `MyType` objects. – Tarec Apr 24 '14 at 12:38