c# - tipo - ¿Por qué no se puede declarar un nombre de variable duplicado en un ámbito local anidado?
las variables locales con tipo implícito se deben inicializar (9)
"El alcance de la variable local o constante se extiende hasta el final del bloque actual. No puede declarar otra variable local con el mismo nombre en el bloque actual o en cualquier bloque anidado". C # 3.0 en una Nutshell, http://www.amazon.com/3-0-Nutshell-Desktop-Reference-OReilly/dp/0596527578/
"El espacio de declaración de variable local de un bloque incluye cualquier bloque anidado. Por lo tanto, dentro de un bloque anidado no es posible declarar una variable local con el mismo nombre que una variable local en un bloque envolvente". Ámbitos de aplicación variable, MSDN, http://msdn.microsoft.com/en-us/library/aa691107%28v=vs.71%29.aspx
En una nota lateral, esto es todo lo contrario a las reglas de JavaScript y F # scoping.
Basado en esta question reciente, no entiendo la respuesta proporcionada. Parece que deberías ser capaz de hacer algo como esto, ya que sus ámbitos no se superponen
static void Main()
{
{
int i;
}
int i;
}
Este código no se puede compilar con el siguiente error:
Una variable local llamada ''i'' no se puede declarar en este ámbito porque daría un significado diferente a ''i'', que ya se usa en un alcance ''secundario'' para denotar algo más
Acabo de compilar esto en GCC como C y como C ++. No recibí ningún mensaje de error por lo que parece ser una sintaxis válida.
Su pregunta está etiquetada como .net y como c. ¿Debería etiquetarse como c #? Ese lenguaje puede tener reglas diferentes que C.
Aquí está su respuesta de http://msdn.microsoft.com/en-us/library/aa691107%28v=vs.71%29.aspx :
... El espacio de declaración de variable local de un bloque incluye cualquier bloque anidado. Por lo tanto, dentro de un bloque anidado no es posible declarar una variable local con el mismo nombre que una variable local en un bloque envolvente.
Desde la http://msdn.microsoft.com/en-us/library/aa691107%28v=vs.71%29.aspx
El espacio de declaración de variable local de un bloque incluye cualquier bloque anidado. Por lo tanto, dentro de un bloque anidado no es posible declarar una variable local con el mismo nombre que una variable local en un bloque envolvente.
Esencialmente, no está permitido porque, en C #, sus ámbitos realmente se superponen.
editar: solo para aclarar, el alcance de C # se resuelve en el nivel de bloque, no línea por línea. Entonces, si bien es cierto que no puede referirse a una variable en el código que viene antes de su declaración, también es cierto que su alcance se extiende hasta el comienzo del bloque.
En C, debe poner toda la declaración de la variable al comienzo de un bloque. Necesitan llegar todos directamente después de la apertura {
antes de cualquier otra declaración en este bloque).
Entonces, lo que puedes hacer para que compile es esto:
static void Main()
{
{
int i;
}
{
int i;
}
}
Esta ha sido una regla en C # desde la primera versión.
Permitir ámbitos superpuestos solo generaría confusión (de los programadores, no del compilador).
Así que ha sido prohibido a propósito.
No creo que ninguna de las respuestas hasta ahora haya obtenido la línea crucial de la especificación.
De la sección 8.5.1:
El alcance de una variable local declarada en una declaración de variable local es el bloque en el que se produce la declaración . Es un error referirse a una variable local en una posición textual que precede al declarador de variable local de la variable local. Dentro del alcance de una variable local, es un error en tiempo de compilación declarar otra variable local o constante con el mismo nombre.
(Énfasis mío)
En otras palabras, el alcance de la variable "posterior" incluye la parte del bloque anterior a la declaración, es decir, incluye el bloque "interno" que contiene la variable "anterior".
No puede hacer referencia a la variable posterior en un lugar anterior a su declaración, pero aún está dentro del alcance.
No se trata de superposición de ámbitos. En C # un nombre simple no puede significar más de una cosa dentro de un bloque donde se declara. En su ejemplo, el nombre i
significa dos cosas diferentes dentro del mismo bloque externo.
En otras palabras, debería poder mover una declaración de variable a cualquier lugar dentro del bloque donde se declaró sin hacer que los ámbitos se superpongan. Desde que cambiaste tu ejemplo a:
static void Main()
{
int i;
{
int i;
}
}
causaría que los ámbitos de las diferentes variables i
solapen, su ejemplo es ilegal.
Para C #, ISO 23270 ( Tecnología de la información - Lenguajes de programación - C # ), §10.3 ( Declaraciones ) dice:
Cada bloque , switch-block , for-statement , foreach-statement o using-statement crea un espacio de declaración para variables locales y constantes locales llamado espacio de declaración de variable local . Los nombres se introducen en este espacio de declaración a través de declaraciones de variables locales y declaraciones de constantes locales .
Si un bloque es el cuerpo de un constructor, método o declaración de operador de instancia, o un descriptor de acceso get o set para una declaración de indexador, los parámetros declarados en dicha declaración son miembros del espacio de declaración de variable local del bloque.
Si un bloque es el cuerpo de un método genérico, los parámetros de tipo declarados en dicha declaración son miembros del espacio de declaración de variable local del bloque.
Es un error que dos miembros de un espacio de declaración de variable local tengan el mismo nombre. Es un error que un espacio de declaración de variable local y un espacio de declaración de variable local anidado contengan elementos con el mismo nombre.
[ Nota: por lo tanto, dentro de un bloque anidado no es posible declarar una variable local o constante con el mismo nombre que una variable local o constante en un bloque envolvente. Es posible que dos bloques anidados contengan elementos con el mismo nombre siempre que ninguno de los bloques contenga el otro. nota final ]
Asi que
public void foobar()
{
if ( foo() )
{
int i = 0 ;
...
}
if ( bar() )
{
int i = 0 ;
...
}
return ;
}
es legal, pero
public void foobar()
{
int i = 0 ;
if ( foo() )
{
int i = 0 ;
...
}
...
return ;
}
no es legal Personalmente, creo que la restricción es bastante molesta. Puedo ver emitir una advertencia del compilador sobre la superposición del alcance, pero ¿un error de compilación? Demasiado cinturón y tirantes, en mi humilde opinión. Sin embargo, pude ver la virtud de una opción de compilación y / o pragma (tal vez -pedantic
/ -practical
, #pragma pedantic
-practical
vs #pragma practical
, B^)
).