Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't change struct's members value inside generic collections

Imagine this struct :

        struct Person
        {
             public string FirstName { get; set; }
             public string LastName { get; set; }
        }

And following code :

        var list = new List<Person>();
        list.Add(new Person { FirstName = "F1", LastName = "L1" });
        list.Add(new Person { FirstName = "F2", LastName = "L2" });
        list.Add(new Person { FirstName = "F3", LastName = "L3" });

        // Can't modify the expression because it's not a variable
        list[1].FirstName = "F22";

When I want to change Property's value it gives me the following error:

Can't modify the expression because it's not a variable

While, when I tried to change it inside an array such as Person[] it worked without any error.Is there any problem with my code when using with generic collections?

like image 232
saber Avatar asked Feb 18 '13 20:02

saber


2 Answers

When you return the struct via the List[] indexer, it returns a copy of the entry. So if you assigned the FirstName there, it would just be thrown away. Hence the compiler error.

Either rewrite your Person to be a reference type class, or do a full reassignment:

Person person = list[1];
person.FirstName = "F22";
list[1] = person;

Generally speaking, mutable structs bring about issues such as these that can cause headaches down the road. Unless you have a really good reason to be using them, you should strongly consider changing your Person type.

Why are mutable structs “evil”?

like image 144
Chris Sinclair Avatar answered Oct 13 '22 10:10

Chris Sinclair


Obviously a part of the question is still unanswered. What is difference between List<Person> and Person[]. In term of getting element by index the List calls indexer (method) which returns copy of value-type instance, in opposite array by index returns not a copy but managed pointer to element at the index (used special IL instruction ldelema).

Of course mutable value-types are evil as mentioned in other answers. Look at the simple example.

var en = new {Ints = new List<int>{1,2,3}.GetEnumerator()};
while(en.Ints.MoveNext())
{
    Console.WriteLine(x.Ints.Current);
}

Surprised?

like image 21
Hamlet Hakobyan Avatar answered Oct 13 '22 10:10

Hamlet Hakobyan