2010-10-09 19 views
5


Hace algún tiempo leí que foreach funciona con "copias" de objetos y, por lo tanto, puede utilizarse para recuperar información en lugar de su actualización. No lo entiendo, ya que es completamente posible recorrer la lista de clases y cambiar su campo. ¡Gracias!C# Diferencia entre Foreach y para (no rendimiento)

Respuesta

9

Lo que puede ha leído es que no se puede modificar una colección al iterar sobre ella usando foreach mientras que usted puede (si usted tiene cuidado) usando un bucle for. Por ejemplo:

using System; 
using System.Collections.Generic; 

class Test 
{ 
    static void Main() 
    { 
     var list = new List<int> { 1, 4, 5, 6, 9, 10 }; 


     /* This version fails with an InvalidOperationException 
     foreach (int x in list) 
     { 
      if (x < 5) 
      { 
       list.Add(100); 
      } 
      Console.WriteLine(x); 
     } 
     */ 

     // This version is okay 
     for (int i = 0; i < list.Count; i++) 
     { 
      int x = list[i]; 
      if (x < 5) 
      { 
       list.Add(100); 
      } 
      Console.WriteLine(x);    
     } 
    } 
} 

Si eso es no lo que se está refiriendo a, por favor dar más detalles - que es difícil de explicar lo que ha leído sin saber exactamente lo que dijo.

+0

Jon, gracias. Sí, lo leí y entiendo que no puedo eliminar un elemento de, por ejemplo, un arreglo si lo atraviesa. Pero creo que puedo modificar el contenido de cada elemento, ¿verdad? – Radusko

+0

Otra advertencia es que foreach puede implementarse de manera muy diferente que el indexador utilizado por for(). En el caso de la colección SelectedItems de la lista, hace una GRAN diferencia en términos de rendimiento. – EricLaw

+0

@Radusko: Sí, puede modificar los datos en el objeto al que se hace referencia ... aunque si se trata de un tipo de valor, igual tratará con una copia. (Afortunadamente, no tendrás que lidiar con tipos de valores mutables). –

1

No se puede modificar el elemento en un foreach:

var list = new List<string>(); 
list.AddRange(new string[] { "A", "B", "C" }); 

foreach (var i in list) 
{ 
    // compilation error: Cannot assign 'i' because it is a 'foreach iteration variable' 
    i = "X"; 
} 

Aunque cuando se trabaja con for que está accediendo al elemento en la lista con su índice, y no el iterador, por lo que de esta manera se puede modificar la colección .

+0

En realidad, puedes modificar los elementos (si pueden modificado) que son tipos de referencia. No puede reemplazarlos, agregarlos ni eliminarlos. La razón por la que su código no funcionará es porque una cadena es inmutable. Una vez creada, una cadena no se puede modificar de ninguna manera. parece ser una modificación en realidad es un reemplazo de una cadena por otra. Por lo tanto, en la ilustración que proporcionó arriba reemplaza uno de los elementos (o elimina uno y agrega uno) y no está permitido al enumerar una colección. – Kirk

1

foreach usa un iterador para obtener cada elemento de una secuencia. La secuencia puede ser Cualquier cosa que implemente IEnumerable. El IEnumerable no necesita ser finito (la secuencia 0 1 2 3 4 ... 1000 ...) es IEnumerable.

para es sólo una C# construcciones que le permiten declarar un bucle (utilizado para hacer todo tipo de cosas, no sólo iteración a través de colecciones)

Vale la pena señalar que la aplicación de iteración de .NET para las colecciones hace no es compatible con la modificación de secuencia durante la iteración.

1

foreach está utilizando IEnumerable para recorrer la colección. Esto hace que sea imposible modificar esta colección (eliminar, agregar elementos), pero aún puede modificar objetos dentro, si son tipos de referencia.

for es una combinación simple de bucle simple combinado con acceso directo a los elementos en la colección. No hay ningún tipo de bloqueo mientras este ciclo está en marcha.

0

compararlo con un campo de sólo lectura:

private readonly List<int> MyList = new List<int>(); 

Ahora, en este código no puedo hacer MyList = new List<int>() como que alterar lo MyList puntos a, pero puede alterar la lista señaló con MyList.Add(3).

Del mismo modo, no se puede alterar la variable utilizada por el foreach iteración, pero puedo lo que se refiere a:

foreach(List<int> lst in MyListOfLists) 
{ 
    lst = new List<int>(); // not allowed 
    lst.Add(3); // allowed 
} 

Por último, el empadronador utilizado para implementar foreach no está obligado a seguir siendo válido si la colección subyacente es que se utiliza:

foreach(int x in SomeEnumerable) 
{ 
    if(x != 0) 
     SomeEnumerable.Add(0); 
} 

Suponiendo que Add modifica SomeEnumerable entonces el trabajo por encima de fuerza , es podría "trabajar" de una manera extraña y difícil de entender y podría lanzar una excepción. No se garantiza ningún comportamiento con dicho código y la modificación de una colección durante la enumeración se considera incorrecta por este motivo.

Cuestiones relacionadas