c# - logicos - operadores en programacion
¿Por qué los operadores de asignación(=) no son válidos en un bucle foreach? (10)
Aquí está su código:
foreach (string item in sArray)
{
item = "Some assignment./r/n";
}
Aquí hay una aproximación aproximada de lo que hace el compilador con esto:
using (var enumerator = sArray.GetEnumerator())
{
string item;
while (enumerator.MoveNext())
{
item = enumerator.Current;
// Your code gets put here
}
}
La IEnumerator<T>.Current
es de solo lectura, pero eso no es realmente relevante aquí, ya que está intentando asignar la variable del item
local a un nuevo valor. La verificación en tiempo de compilación que le impide hacerlo se realiza básicamente para protegerlo de hacer algo que no funcionará como espera (es decir, cambiar una variable local y no tener efecto en la recopilación / secuencia subyacente).
Si desea modificar las partes internas de una colección indexada como una string[]
mientras se enumera, la forma tradicional es usar un bucle for
lugar de un foreach
:
for (int i = 0; i < sArray.Length; ++i)
{
sArray[i] = "Some assignment./r/n";
}
¿Por qué los operadores de asignación (=) no son válidos en un bucle foreach
? Estoy usando C #, pero supongo que el argumento es el mismo para otros idiomas que admiten foreach
(por ejemplo, PHP). Por ejemplo, si hago algo como esto:
string[] sArray = new string[5];
foreach (string item in sArray)
{
item = "Some assignment./r/n";
}
Aparece un error, "No se puede asignar a ''elemento'' porque es una ''variable de iteración de foreach''".
Debido a que no puede usar un bucle foreach
para modificar una matriz a través de la cual está haciendo un bucle El bucle recorre la matriz, por lo que si intenta modificar la iteración, se puede producir un comportamiento inesperado. Además, como han señalado Darin y DMan, estás iterando a través de un IEnumerable
que es de solo lectura.
PHP hace una copia de la matriz en su bucle foreach
e itera a través de esa copia, a menos que use referencias, en cuyo caso modificará la matriz en sí.
El bucle foreach
está diseñado para recorrer los objetos de una colección, no para asignar cosas, es simplemente un diseño del lenguaje.
Además, desde MSDN:
"Este error se produce cuando se produce una asignación a una variable en un contexto de solo lectura. Los contextos de solo lectura incluyen variables de iteración de foreach, variables de uso y variables fijas. Para resolver este error, evite las asignaciones a una variable de declaración al usar bloques, declaraciones de foreach , y declaraciones fijas ".
La palabra clave foreach simplemente enumera las instancias de IEnumerable (obteniendo instancias de IEnumerator llamando al método GetEnumerator ()). IEnumerator es de solo lectura, por lo tanto, los valores no se pueden cambiar usando IEnumerator = no se pueden cambiar usando el contexto foreach.
En general, si está tratando de hacer esto, necesita pensar mucho sobre su diseño, porque probablemente no esté usando la mejor construcción. En este caso, la mejor respuesta probablemente sería
string[] sArray = Enumerable.Repeat("Some assignment./r/n", 5).ToArray();
Las construcciones de nivel superior casi siempre son utilizables en lugar de este tipo de bucle en C #. (Y C ++, pero eso es otro tema)
Foreach está diseñado para interactuar a través de la matriz una vez, sin repetir ni saltar (aunque puede omitir alguna acción dentro de la construcción foreach utilizando la palabra clave continue). Si desea modificar el elemento actual, considere usar un bucle for en su lugar.
No puede modificar una lista que se está repitiendo a través de un "ForEach".
La mejor opción es simplemente crear una lista temporal para almacenar los elementos que desea utilizar.
No puedes modificar una matriz por la que estás foreaching. Utilice el siguiente código en su lugar:
string[] sArray = new string[5];
for (int i=0;i<sArray.Length;i++)
{
item[i] = "Some Assignment./r/n";
}
Porque la especificación del lenguaje lo dice.
Pero en serio, no todas las secuencias son matrices o cosas que pueden modificarse o escribirse lógicamente. Por ejemplo:
foreach (var i in Enumerable.Range(1, 100)) {
// modification of `i` will not make much sense here.
}
Si bien hubiera sido técnicamente posible tener i = something;
modifique una variable local, puede ser engañosa (puede pensar que realmente cambia algo debajo del capó y no sería el caso).
Para admitir este tipo de secuencias, IEnumerable<T>
no requiere un set
acceso para su propiedad Current
, por lo que es de solo lectura. Por lo tanto, foreach
no puede modificar la colección subyacente (si existe) utilizando la propiedad Current
.
Porque un IEnumerable
es de solo lectura.
Sería perfectamente posible dejar que se altere. Sin embargo, ¿qué significa esto entonces? Se leería como si se modificara la enumeración subyacente, lo que no es (sería posible permitir eso también, pero eso tiene sus propias desventajas).
Entonces tendrías un código que la gente naturalmente leería para indicar algo diferente a lo que realmente sucedió. Teniendo en cuenta que el propósito de un lenguaje informático es que lo entiendan principalmente las personas (los compiladores se ocupan de que el saldo se establezca en su contra, a menos que utilice el ensamblaje, el código de máquina o el nombre apropiado Brainf ** k), esto indicaría una falla en el idioma.