2

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?

Hamid Pourjam
  • 20,441
  • 9
  • 58
  • 74
John Tan
  • 1,331
  • 1
  • 19
  • 35

3 Answers3

3

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 
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
1

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.

Hamid Pourjam
  • 20,441
  • 9
  • 58
  • 74
  • Thanks. But an additional question. What if I need the values of `obj` to persist with every iteration of the loop? For example if `obj.num` depends on the previous value of `obj`? – John Tan Feb 25 '15 at 06:42
  • @JohnTan Well, they're all in the list, so you have access to them. – Rufus L Feb 25 '15 at 06:46
0

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);
}
DevEstacion
  • 1,947
  • 1
  • 14
  • 28
  • @OndrejTucny yah, was in a meeting when i did the code so i didn't have that much time to think. Well the `(2)` just tackles the `"Deep Copy"` he wants – DevEstacion Feb 25 '15 at 12:10