tags:

views:

127

answers:

4

I have a List of structure.In the loop i am trying to modify the object's property,which is happening,but when i (Quick look in Visual studio)look into the list object ,the new value is not reflecting.Is it by virtue that the structure's object cannot be modified when in a collection? I am using generics list with the struct as the type in the list

+1  A: 

If you are using a foreach loop you probably got

Compiler Error CS1654

Error Message Cannot modify members of 'variable' because it is a 'read-only variable type'

This error occurs when you try to modify members of a variable which is read-only because it is in a special construct.

One common area that this occurs is within foreach loops. It is a compile-time error to modify the value of the collection elements. Therefore, you cannot make any modifications to elements that are value types, including structs.

You could however try

struct MyStruct
{
    public int i;
}

List<MyStruct> list = new List<MyStruct> 
        { new MyStruct { i = 1 }, new MyStruct { i = 2 } };

for(int i = 0; i < list.Count; i++)
{
    MyStruct val = list[i];
    val.i++;
    list[i] = val;
}

EDIT

See also Structs Tutorial

Structs vs. Classes

Structs may seem similar to classes, but there are important differences that you should be aware of. First of all, classes are reference types and structs are value types.

astander
Thanks ,I have done the same ,but isnt this creating one more copy of sctruct object in list???
Ravisha
No, this will be replacing the struct at position i in list with the copied struct, with updated value.
astander
A: 

I THINK i know what the problem might be.

struct Astruct
{
   int amember;
}

List < Astruct > listofStructs;

foreach(Astruct A in listofStructs)
{
     A.amember = 1337;
}

if this is what you are doing...

when you use structs in c# they are not referenced but copied! so that means the contents of your list is being COPIED to A, so when you change A it doesn't change the value in the list!

to solve this problem (if this is your problem...) either use CLASSES rather than STRUCTS, that way A would be a reference, OR use a manual iterating for loop instead, ie:

for(int i=0;i < listofStructs.Count;i++)
{
    listofStructs[i].amember = 1337;
}

alternatively, if you’re using a list, you maybe should use an iterator or something... but the above should definitely fix that problem.

matt
Thumbs down.Got following compilation errorError 10 Cannot modify the return value of 'System.Collections.Generic.List<Animation.WidgetResolution>.this[int]' because it is not a variable D:\Designer_Tag\Designer\Animation\AnimationPersistance.cs 182 29 Animation
Ravisha
A: 

Given the information in your post (although I'd have liked to see the code itself), let me put forth the most probable issue and its fix.

   foreach(var s in listOfStructs)
    {
      s.Property = x;
    }

s is assigned to a copy of the actual struct in the collection. s.set_Property is now modifying the copy which is thrown away at the end of the current iteration.

This is because 2 value type variables cannot point to the same instance.

struct1 = new MyStruct(100, 200);
struct2 = struct1;   // struct2 is now a copy of struct1

Now to the problem of how do you modify the instances in a collection:
Get the object to modify in a local variable (copy created). Modify it. Now remove the original object and insert the copy. use listOfStructs[i] = modifiedInstance.

Gishu
+2  A: 

You mention "modify the object's property" in the context of a struct, but importantly a struct is not an object. Other people have answered as to the issue with structs being copied (and changes discarded), but to take that further the real problem here is that you have a mutable (changeable) struct at all. Unless you are on XNA (or similar) there is simply no need.

If you want to be able to change properties, make it a class:

public class Foo {
    public string Bar {get;set;}
}

This is now a reference-type, and your changes (obj.Bar = "abc";) will be preserved through the foreach. If you really want/need a struct, make it immutable:

public struct Foo {
    private readonly string bar;
    public string Bar { get {return bar; }}
    public Foo(string bar) {this.bar = bar;}
}

Now you can't make the mistake of changing the value of a copy; you would instead have to use the indexer to swap the value (list[i] = new Foo("abc");). More verbose (and you can't use foreach), but correct.

But IMO, use a class. Structs are pretty rare, to be honest. If you aren't sure: class.

Marc Gravell
+1 for that Thanks Marc more info is on below after i searched about struct on search http://msdn.microsoft.com/en-us/library/aa288471%28VS.71%29.aspx
Ravisha