Sourabh
Sourabh

Reputation: 35

Modifying a particular item in a list of structures

I have list of structure. I want to modify a particular data from the structure. And the structure is at the particular index location of the List.

I want to do something like this:

struct sample
{
  int a;
  string name;
}

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


for(int i=0; i < list.Count; i++)
{
  list[i].a = someotherlist[i].data;
}

Upvotes: 3

Views: 182

Answers (3)

Sourabh
Sourabh

Reputation: 35

I just modified my code as bellow and it works fine for me

public struct test
        {
            public int data;
            public string name;
            public int port_index;
        }
static void Main(string[] args)
        {
            List<test> look_up = new List<test>();
            test obj;
            obj.data = 1;
            obj.port_index = 0;
            obj.name = "aaaa";
            look_up.Add(obj);
            test obj1;
            obj1.data=3;
            obj1.port_index=1;
            obj1.name="sssss";
            look_up.Add(obj1);
            for(int i=0;i<look_up.Count;i++)
            {
                if (i == 1)
                {
                    test temp = look_up[i];
                    temp.data = 5;
                    look_up[i] = temp;
                }
            }
        }

Upvotes: 0

Marc Gravell
Marc Gravell

Reputation: 1062945

The problem is that the list indexer creates a copy of the struct, i.e. it is really:

for(int i=0; i < list.Count; i++)
{
  var completelyIsolatedClone = list[i];
  completelyIsolatedClone.a = someotherlist[i].data;
}

The compiler is preventing you making an obvious mistake. The code you have uses the get, mutates a separate copy of the data, but never puts it back - so your change doesn't do anything useful. Note that the Mono folks think it would be nice if it worked your way, though: http://tirania.org/blog/archive/2012/Apr-11.html

Note that an array works differently; with an array you are touching the struct in place, so the following would work fine:

for(int i=0; i < list.Count; i++)
{
  someArray[i].a = someotherlist[i].data;
}

Another approach is to copy the data out (the get accessor), mutate it, and put it back:

for(int i=0; i < list.Count; i++)
{
  var completelyIsolatedClone = list[i];
  completelyIsolatedClone.a = someotherlist[i].data;
  list[i] = completelyIsolatedClone;
}

or better, acoid mutable structs completely, perhaps with a method that applies the change to a new copy:

for(int i=0; i < list.Count; i++)
{
  list[i] = list[i].SetA(someotherlist[i].data);
}

where SetA creates a new struct, like DateTime.AddDays etc, i.e.

public SomeType SetA(int a) {
    return new SomeType(this.X, this.Y, a, this.Z);
}

Upvotes: 6

Habib
Habib

Reputation: 223277

The reason you can't do it is because Sample is a struct, if you change it to a class then you can modify it. Structures are passed by value, that is, when a structure is returned by a method, a copy of the structure is returned, not the orginal structure. So when list[i].a = someotherlist[i].data; is run, you are actually modifying the copy and the orginal structure is not being changed. The compilers prevents you from doing this as it is probably not what you had intended.

You may look at this thread Why couldnot I modify the value of item from Generic Collections) ?

Upvotes: 2

Related Questions