0

When I'm finding an item from List and trying to change one of its properties, it just stays unchanged.

// My struct
struct Person
{
    public string name;
    public string surname;
}

// Fill up initial data
persons = new List<Person>();
person = new Person();
person.name = "Name";
person.surname = "Test";
persons.Add(person);

// Here person is found, I can see it by printing person.name and person.surname
Person foundPerson = persons.Find(p => p.surname == "Test");

// Let's change it
foundPerson.name = "Another name";

// But when I print all list's items, the name is still "Name". So previous string hasn't changed the original object.
persons.ForEach(delegate (Person person)
{
    Console.WriteLine("Name: {0}", person.name);
});

What am I missing? What should I do in order to change the original value, which is contained in my list?

weston
  • 54,145
  • 21
  • 145
  • 203
ozahorulia
  • 9,798
  • 8
  • 48
  • 72

2 Answers2

4

Because you are using structs. Structs are processed by value, so when you write

Person person list.Find(p => p.surname == "Test"); 

you get a copy of a person.

Use class instead of struct or write back to list full person struct.

If you still want to use struct you can write

Person foundPerson = persons.Find(p => p.surname == "Test");
int index = persons.IndexOf(foundPerson);
foundPerson.name = "Another name";
persons[index] = foundPerson;
Artem
  • 1,535
  • 10
  • 13
  • Thank you. But if structs are processed by value, there is a strange thing. If I have a List field inside my struct, and if I add something to that list (e.g. `foundPerson.list.Add(someAnotherStruct)`) it will be saved to the original struct from the `persons` list. Why? If what you are saying is true, then the original list should not be affected. – ozahorulia Apr 25 '16 at 11:30
  • Because List is a class, so you store a pointer to the list inside your struct. When you get a copy of a struct you have a copy of a pointer inside it, but this pointer still point to the same list. – Artem Apr 25 '16 at 11:33
2

This is because structs are by-value objects. When you do this

Person foundPerson = persons.Find(p => p.surname == "Test");

foundPerson becomes an independent copy of the Person struct from your list. Any changes made to it are not reflected in the original.

You can fix this by making Person a class. If you have no flexibility to make this change, you could search for an index, and make the change in place, or treat Person as if it were immutable, and assign the modified foundPerson back to the position in the list where it is stored.

Your question provides a perfect illustration why it is a good idea to stay away from mutable structs.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523