2010-07-30 13 views
8

Consideremos el siguiente ejemplo de código:C pregunta # alcance

      // line # 
{      // 1 
         // 2 
    {     // 3 
     double test = 0; // 4 
    }     // 5 
         // 6 
    double test = 0;  // 7 
}      // 8 

Esto da el error

Una variable local llamada 'prueba' no se pueden declarar en este ámbito, ya que daría un significado diferente a 'test', que ya se utiliza en un ámbito 'niño' para denotar algo más

Pero no entiendo por qué? La variable de prueba externa comienza en la línea 7 y no en la línea 2, entonces, ¿dónde está el problema para declarar una segunda variable llamada prueba en la línea 4 con un alcance que termina en la línea 5?

+7

El mensaje de error dice prácticamente todo. Los diseñadores de idiomas lo hicieron de esta manera para alentar a las personas a utilizar diferentes nombres de variables dentro de un bloque delimitado para evitar confusiones, a pesar de que podrían haber escrito el alcance más estrictamente. Por lo tanto, las variables en ámbitos secundarios deben tener nombres exclusivos. –

+1

http://blogs.msdn.com/b/ericlippert/archive/2009/11/02/simple-names-are-not-so-simple.aspx – LukeH

+0

Esto es, creo, un ejemplo del 'pozo del éxito' filosofía en el diseño de las diversas partes de .NET (ref http://blogs.msdn.com/b/brada/archive/2003/10/02/50420.aspx) – AakashM

Respuesta

3

Esta es una pregunta frecuente; ver también:

Lambda variable scope

C# going nuts when I declare variables with the same name as the ones in a lambda

C# variable scoping: 'x' cannot be declared in this scope because it would give a different meaning to 'x'

Variable scope confusion in C#

La respuesta es: leer el mensaje de error con más cuidado. El mensaje de error indica exactamente cuál es el problema: no está permitido usar el mismo nombre simple para significar dos cosas diferentes en el mismo bloque.

Por ejemplo:

class C 
{ 
    int x; 
    void M() 
    { 
     int x; 
    } 
} 

perfectamente legal. Tenga en cuenta que el alcance del exterior x se superpone a el alcance de la x interior. Es no ilegal tener ámbitos superpuestos con el mismo nombre en el alcance en ambos.

Esto no es legal:

class C 
{ 
    int x; 
    void M() 
    { 
     Console.WriteLine(x); // this.x 
     { 
      int x; 
     } 
    } 
} 

De nuevo, los dos ámbitos tanto con una X superposición es perfectamente legal. Lo que es ilegal es que el simple nombre x se utiliza dos dos variables medias diferentes en el mismo bloque - es decir, dentro del bloque exterior de M(), que contiene el bloque interior de M.

Programas donde el mismo nombre simple es utilizarse para significar dos cosas diferentes en el mismo bloque se confuso y bug propensos y por lo tanto son ilegal en C#.

Para más detalles leer mis artículos sobre el tema:

http://blogs.msdn.com/b/ericlippert/archive/tags/simple+names/

+0

¡Muchas gracias por esta respuesta detallada! –

10

variables están en el ámbito dentro del bloque que se declaran en, no importa cuál es la línea que se encuentran.

leer sobre scopes en la especificación del lenguaje C#.

De la especificación:

El alcance de una variable local declarada en una declaración-variable-local (Section 8.5.1) es el bloque en el que se produce la declaración.

Y:

Scopes se pueden anidar, y un alcance interior puede redeclare el significado de un nombre de un alcance exterior. (Esto no significa, sin embargo, eliminar la restricción impuesta por la Sección 3.3 que dentro de un bloque anidado no es posible declarar una variable local con el mismo nombre que una variable local en un bloque que lo contiene.)

+0

Gracias por la explicación y enlace, Oded/Robert! BTW aquí está la cita relevante de la página enlazada http://msdn.microsoft.com/en-us/library/aa691132%28VS.71%29.aspx: "Los ámbitos se pueden anidar, y un ámbito interno puede redeclarar el significado de un nombre de un alcance externo. (Sin embargo, esto no elimina la restricción impuesta por la Sección 3.3 que dentro de un bloque anidado no es posible declarar una variable local con el mismo nombre que una variable local en un bloque envolvente.) " –

+0

@ stefan.at.wpf - verdadero. Respuesta actualizada para incluir este bit de información. – Oded

0

+1 , Estoy de acuerdo contigo, pero no es cómo se escribe la especificación. Hace que escribir el compilador sea más fácil, estoy seguro. Además, creo que podría argumentarse que es preferible no hacer esto de todos modos para hacer que el código sea más fácil de entender.

+0

Gracias tster, también creo que esta es la razón principal y sí, realmente no es útil hacer algo. como en mi ejemplo (simplemente cambie el orden de los bloques ...), simplemente no entendí por qué en el primer momento ;-) –

+2

I * le aseguro * que no * * hace que escribir el compilador sea más fácil. El código en el compilador que implementa esta regla es uno de los códigos más caóticos y confusos que he visto en mi vida. Hay * muchos * errores en este código con los que nunca se encontrará porque son casos de esquina extremadamente oscuros. La razón de esta característica es porque evita errores en el código de usuario, no porque hace que mi trabajo sea más fácil. Hace mi trabajo un poco más difícil. –

+0

@Eric Lippert, gracias por el testimonio de expertos. – tster