John Tan
John Tan

Reputation: 1385

Deep copy of an object into List

I have a loop:

List<A> list = new List<A>();
A obj = new A();

for (int i = 0; i < 10; ++i)
{
    obj.num = i; // Assigns the current i to the num attribute inside obj
    list.Add(obj);
}

However, in this case, whenever I modify obj, the previous instances of obj already added into the list will be modified. How do I write the code such that whatever that is added into the list has no more reference to the current value of obj?

Upvotes: 2

Views: 1512

Answers (3)

DevEstacion
DevEstacion

Reputation: 1967

That's happening because probably A obj = new A(); is a ByReference object. So whenever you're in the loop, it's also changing the object you added on the List.

What you can do is either

  1. Create the object inside the loop and then add it.

    for (int i = 0; i < 10; ++i)
    {
        A obj = new A(); // create here so it's a new object always
        obj.num = i; // Assigns the current i to the num attribute inside obj
        list.Add(obj);
    }
    
  2. Make the A type IClonable

    class A : ICloneable
    {
        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }
    

and then just cast in before adding.

List<A> list = new List<A>();
A obj = new A();
obj.num = 0;

for (int i = obj.num; i < 10; ++i)
{
    var clonedObj = obj.Clone() as A; // cast to be able to add in the collection
    clonedObj.num = i;
    list.Add(clonedObj);
}

Upvotes: 0

Hamid Pourjam
Hamid Pourjam

Reputation: 20754

you should move declaration of obj variable inside for loop

List<A> list = new List<A>();

for (int i = 0; i < 10; ++i)
{
    A obj = new A();
    obj.num = i; // Assigns the current i to the num attribute inside obj
    list.Add(obj);
}

it is all just about variable scopes. here obj scope is inside a for loop iteration. if you want to use a variable between iterations you should define it out of for loop like the way you have declared obj before.

Upvotes: 1

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

You can create a new List<A> via Linq instead of adding:

List<A> list = Enumerable
  .Range(0, 10)
  .Select(i => new A() { num = i })
  .ToList();

If you prefer adding

List<A> list = new List<A>();

for (int i = 0; i < 10; ++i)
  list.Add(new A() {num = i}); // <- Adding new (copied) instance 

Upvotes: 3

Related Questions