0

I make two List< Test> called listA and listB. I save a peace of data in listA. I copy the data from listA to listB. I change the data in listB. When I change the data in listB it also changes in listA – is it posible to avoid this?

I hope you can help me out there :o)

public class Test
{
    public string Name { get; set; }
}

static void Test()
    {
        List<Test> listA = new List<Test>();
        List<Test> listB = new List<Test>();

        listA.Add(new Test { Name = "A" });
        listB.AddRange(listA);

        //I change the data in listB and the data in listA also get changed. 
        listB.First().Name = "B";
        Console.WriteLine("listA: {0} listB: {1}", listA.First().Name, listB.First().Name);

        //Can I avoid the change of data in listA?
    }
Kenneth Bo Christensen
  • 2,256
  • 2
  • 18
  • 21
  • change class Test to Struct Test and see what happens – rerun Jan 29 '13 at 20:27
  • You have a misconception here. Regardless of the `List` instances being different, the `Test` instances they contain are the same, so if you change something inside a `Test` instance, it's going to be changed regardless of which `List` instance you accessed it thru. – Federico Berasategui Jan 29 '13 at 20:28
  • Possible duplicate of http://stackoverflow.com/questions/9622211/how-to-make-correct-clone-of-the-listmyobject – David L Jan 29 '13 at 20:28
  • possible duplicate of [How do you do a deep copy an object in .Net (C# specifically)?](http://stackoverflow.com/questions/129389/how-do-you-do-a-deep-copy-an-object-in-net-c-specifically) – John Koerner Jan 30 '13 at 03:51

4 Answers4

8

You'll have to copy the objects in listA when adding them to listB:

listB.AddRange(listA.Select(t => new Test { Name = t.Name }));

At the moment, you are just copying the references in listA into listB, and these references point to the same object. This is why modifying them through listA makes the changes visible in listB.

Lee
  • 142,018
  • 20
  • 234
  • 287
  • 1
    And you could encapsulate the copying part into a method, called something like `Clone()`. – svick Jan 29 '13 at 20:31
  • Thanks Lee! My real Test Clas has 15 properties. Are there a diferent apporach than writing them all: listB.AddRange(listA.Select(t => new Test { Name = t.Name, Name2 = t.Name2 ... Name15 = t.Name15 }).ToList()); ? – Kenneth Bo Christensen Jan 29 '13 at 21:00
1

You will have to create new instances of the Test object.

You could add a copy method to your test class to make it a bit easier to copy the members using MemberwiseClone, this will be good if you have losts of properties to copy without needing big select statments to populate each property.

public class Test
{
    public string Name { get; set; }

    public Test Copy()
    {
        return (Test)this.MemberwiseClone();
    }
}

Then you can use where needed in your code.

  List<Test> listA = new List<Test>();
  List<Test> listB = new List<Test>();
  listA.Add(new Test { Name = "A" });

  listB.AddRange(listA.Select(x => x.Copy()));
sa_ddam213
  • 42,848
  • 7
  • 101
  • 110
0

This also works because Test obj in listB is a instance different than Test obj in listA

 listA.ForEach((item) =>
    {
        listB.Add(new Test {Name = item.Name});
    });
Nick
  • 4,192
  • 1
  • 19
  • 30
0

For more complex objects you can implement a clone method as described in the comment above:

public Test Clone()
{
     return new Test { Name = this.Name};
}

The code above would be modified as follows:

listB.AddRange(listA.Select(t => t.Clone()));

There is also an ICloneable interface in .NET but it is not recommend to use this interface. I included a link to another question that contains a discussion of this interface.

Why should I implement ICloneable in c#?

Community
  • 1
  • 1
Roland Schaer
  • 1,656
  • 1
  • 22
  • 30