Why I am not able to modify List items?
struct Foo
{
public string Name;
}
Foo foo = new Foo();
foo.Name = "fooNameOne";
List<Foo> foos = new List<Foo>();
foos.Add(foo);
// Cannot modify the return value of
// 'List<Foo>.this[int]' because it is not a variable
//foos[0].Name = "fooNameTwo";
Foo tempFoo = foos[0];
tempFoo.Name = "fooNameTwo";
Console.WriteLine(foos[0].Name); // fooNameOne
EDIT:
I want to leave the structure for Foo. How should I proceed? foos[0] = tempFoo? little bit complicated just for an assignment?!.
Here’s the thing.
You say this:
Yeah, well, that’s just it. What you need is an assignment, not a modification. Value types (structs) are generally supposed to be treated as values.
Take
int. If you had aList<int>calledints, how would you change the value atints[0]?Something like this, right?
Notice there’s no way to do something like this:
That’s because
Int32is an immutable struct. It is intended to be treated as a value, which cannot be changed (so anintvariable can only be assigned to something new).Your
Foostruct is a confusing case because it can be mutated. But since it’s a value type, only copies are passed around (same as withint,double,DateTime, etc. — all the value types we deal with on a regular basis). For this reason you cannot mutate an instance "from afar"–that is, unless it is passed to you by ref (using therefkeyword in a method call).So the simple answer is, yeah, to change a
Fooin aList<Foo>, you need to assign it to something new. But you really shouldn’t have a mutable struct to begin with.Disclaimer: As with almost any advice you can receive, in anything, this is not a 100% hard rule. The very skilled developer Rico Mariani wrote the
Point3dstruct to be mutable for good reasons, which he explained on his blog. But this is a case of a very knowledgeable developer knowing exactly what he’s doing; in general, as a standard approach to writing value types versus reference types, value types should be made immutable.In response to your comment: so when you are dealing with a mutable struct like
Point, basically you need to do something like this:Or, alternatively:
The reason I wouldn’t do…
…is that here you’re copying the value at
points[0]twice. Remember that accessing thethisproperty by index is basically a method call. So that code is really doing this:Note the excessive call to
get_Item(making an additional copy for no good reason).