Atualização struct em loop foreach em C #
Pergunta
Eu tenho esse código (C #):
using System.Collections.Generic;
namespace ConsoleApplication1
{
public struct Thing
{
public string Name;
}
class Program
{
static void Main(string[] args)
{
List<Thing> things = new List<Thing>();
foreach (Thing t in things) // for each file
{
t.Name = "xxx";
}
}
}
}
Ele não irá compilar.
O erro é:
Cannot modify members of 't' because it is a 'foreach iteration variable'
Se eu mudar Thing
a um class
em vez de um struct
, no entanto, ele faz compilação.
Por favor, alguém pode explicar o que está acontecendo?
Solução
Mais ou menos o que diz, o compilador não permitem alterar (partes) do var looping em um foreach.
Basta usar:
for(int i = 0; i < things.Count; i+= 1) // for each file
{
things[i].Name = "xxx";
}
E funciona quando Thing
é uma classe, porque então o seu var looping é uma referência, e você só fazer alterações no objeto referenciado, não para a própria referência.
Outras dicas
A struct há nenhum tipo de referência, mas um tipo de valor.
Se você teria um class
em vez de um struct
para Thing
, o loop foreach criaria uma variável de referência para você, que apontaria para o elemento correto em que você lista. Mas uma vez que é um tipo de valor, ele só funciona com uma cópia do seu Thing
, que é, neste caso, a variável de iteração.
A struct é um tipo de valor, mas uma classe é um tipo de referência. É por isso que compila quando Esta é uma classe, mas não quando é uma struct
Veja mais: http://www.albahari.com/valuevsreftypes.aspx
Uma sintaxe alternativa que prefiro @ solução de Henk é isso.
DateTime[] dates = new DateTime[10];
foreach(int index in Enumerable.Range(0, dates.Length))
{
ref DateTime date = ref dates[index];
// Do stuff with date.
// ...
}
Se você não está fazendo uma quantidade razoável de trabalho no circuito, em seguida, ter de repetir a indexação em todos os lugares é mais fácil no olho imo.
P.S. DateTime é realmente um exemplo realmente pobre como ele não tem quaisquer propriedades que você pode definir, mas você começa a foto.