Não é possível alterar o valor dos membros da estrutura dentro de collections genéricas

Imagine essa struct :

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

E seguindo o código:

  var list = new List(); 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"; 

Quando eu quero mudar o valor da Property , isso me dá o seguinte erro:

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

Enquanto, quando tentei alterá-lo dentro de uma matriz como Person[] ele funcionou sem nenhum erro. Existe algum problema com meu código ao usar collections genéricas?

Quando você retorna o struct através do indexador List[] , ele retorna uma cópia da input. Então, se você atribuiu o FirstName aqui, seria apenas jogado fora. Daí o erro do compilador.

Reescreva sua Person para ser uma class tipo de referência ou faça uma reatribuição completa:

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

De um modo geral, as estruturas mutáveis ​​trazem questões como essas que podem causar dores de cabeça no caminho. A menos que você tenha uma boa razão para usá-los, você deve pensar em mudar seu tipo de Person .

Por que as estruturas mutáveis ​​são “malignas”?

Obviamente, uma parte da questão ainda não foi respondida. Qual é a diferença entre List e Person[] . Em termos de obtenção de elemento por índice, o List chama o indexador (método) que retorna a cópia da instância do tipo valor, na matriz oposta pelo índice retorna não uma cópia, mas o ponteiro gerenciado para o elemento no índice (usado ldelema instrução IL).

Claro que os tipos de valores mutáveis ​​são maus, como mencionado em outras respostas. Veja o exemplo simples.

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

Surpreso?

Refazer sua struct como tal:

  struct Person { private readonly string firstName; private readonly string lastName; public Person(string firstName, string lastName) { this.firstName = firstName; this.lastName = lastName; } public string FirstName { get { return this.firstName; } } public string LastName { get { return this.lastName; } } } 

E seguindo o código como:

  var list = new List(); list.Add(new Person("F1", "L1")); list.Add(new Person("F2", "L2")); list.Add(new Person("F3", "L3")); // Can modify the expression because it's a new instance list[1] = new Person("F22", list[1].LastName); 

Isto é devido à semântica da cópia de struct . Torne-o imutável e trabalhe dentro dessas restrições e o problema desaparece.