c# - Alcance de un ciclo ''for'' en la declaración de una variable
for-loop scope (6)
Me enfrenté a este extraño comportamiento cuando estaba codificando. Entonces lo pregunto aquí.
¿Cuál es el alcance de un bucle for
al declarar variables?
Este código compila bien
for (int i = 0; i < 10; i++) { }
for (int i = 0; i < 10; i++) { }
Esto significa que ambos int i
no están en el mismo alcance.
Pero este código no compila.
for (int i = 0; i < 10; i++) { }
int i; // Conflicts with both first loop and second one.
for (int i = 0; i < 10; i++) { }
Esto significa que int i
en medio de bucles tiene el mismo alcance de primer bucle y el segundo bucle.
Pero, ¿cómo puede int i
en dos bucles for
tener un alcance diferente, pero el mismo alcance con middle int i
? Porque actualmente los veo en el mismo nivel.
Sé que el segundo código no se compila. ¿Por qué compila el primer código y luego si hay un problema en los ámbitos? ¿Es esta una excepción dentro del compilador?
El alcance de un bucle for, for(INIT; COND; INCR) { BLOCK }
es idéntico en el alcance a
{
INIT;
while (COND) {
BLOCK;
INCR;
}
}
Por lo tanto, un bucle for se puede considerar mejor como dos ámbitos anidados. (Nota: la conversión anterior de a while
no captura correctamente el comportamiento de continue
. Sin embargo, esta pregunta no se centra en eso)
El problema con el que te encuentras con la int i
fuera del bucle for es algo llamado "shadowing". En C ++, si declaró una variable de ámbito con el mismo nombre que algo en un ámbito externo, lo "sombreó", cubriéndolo silenciosamente hasta que finalizó el alcance. Cuando desarrollaron C #, sintieron que esto era demasiado contrario a la intuición y demasiado propenso a errores. En C # es un error de sintaxis para sombrear una variable desde un ámbito externo. Al introducir int i
en el alcance externo, ahora es ilegal que los bucles for
introduzcan ellos mismos.
El compilador C # no verifica si una variable fue declarada antes o después de otra variable. Todo lo que importa es el alcance. La variable i
declarada entre bucles entra en conflicto con el segundo bucle, porque si usa i
dentro del bucle, no hay forma de distinguir cuál i
gustaría usar. En cuanto al primer ciclo, aún se muestra un error, porque el bloque donde i
se declara encapsula también el primer ciclo.
Por ejemplo, lo siguiente no se compilará, aunque j
no sea visible fuera de las llaves internas, por lo que no debería haber ninguna ambigüedad con respecto a i
:
{
{
int i = 1;
int j = 1;
}
int i = 0; // compiler error: A local variable i cannot be declared in this scope (...)
// j is not visible here
}
Editar con respecto al comentario:
¿Por qué está bien lo siguiente?
{
for(int i = 1; i < 10; i++) {}
for(int i = 1; i < 10; i++) {}
}
Cuando declaras una variable for
loop, es visible solo dentro del bloque loop . Eso significa que los ámbitos de ambas variables son disjuntos, ya que no hay una línea de código donde un bloque "se superpone" al otro.
La variable declarada en for loop tiene solo alcance adentro para loop block, pero cuando declaras una variable afuera para loop, no puedes tener la misma variable dentro del ciclo for, porque confunde al compilador con qué variable quieres decir para el cuerpo del ciclo.
Me gustaría tomar su código como ejemplo:
int i =0;
for (int i = 0; i < 10; i++)
{
i = i+1; // now compiler is confused which i you mean here, so i complains on compile time that you have two with same name
}
Entonces, si lo declaras entre bucles como lo hiciste, la variable i
tiene alcance en ambos bucles for para que esté accesible en ambos bucles for, por lo que si eliminas el primer bucle se seguirá quejando debido al alcance global de la variable fuera del bucle.
for (int i = 0; i < 10; i++)
{
i = i+1; // now compiler is still confused which i you mean
}
int i =0;
No creo que importe dónde pones int i;
.
El compilador primero escanea el campo, luego de lo cual comienza a buscar expresiones. No compila porque el i
ya es reconocido como un campo.
No hay nada extraño que esté pasando. En el segundo caso, ha definido una i
externa y luego intenta redefinirla en cada ciclo.
Las variables declaradas en una instrucción for
son locales para el ciclo, pero ya definió otra variable con el mismo nombre en el ámbito externo.
Creo que ya ha hecho otra pregunta de alcance suponiendo que el alcance de una variable comienza desde el punto de declaración.
El alcance de una variable es el bloque en el que está definido, no se ve afectado por su ubicación. Si bien el compilador se negará a usar la variable antes de la declaración, todavía está en el alcance
int i
; Usted declara que el bucle está disponible para la función actual. O declara solo outer int i
, elimina int i
de ambos loops o simplemente elimina esta variable externa.