2012-04-10 5 views
56

Tengo curiosidad acerca de esta cosa ... ver ejemplo:¿Cuál es el propósito de las llaves adicionales en la caja del interruptor?

switch(x) 
{ 
    case(a): 
     { 
     //do stuff 
     } 
     break; 
    case(b): 
     //do stuff 
     break; 
} 

Toda mi vida lo he hecho, como el caso b, pero desde C# permite que lo use, y Visual Studio me permite a colapsar esa cosa, tengo curiosidad, ¿cuál es la diferencia real entre el caso a (con llaves) y el caso b?

+15

No hay ninguna diferencia, excepto que las variables definidas en caso de que un sólo son visibles en ese bloque. –

+3

Nada realmente.Es solo que a veces quieres crear y usar objetos que tengan un alcance para el caso. Sin corchetes, cualquier cosa que defina tiene un alcance más amplio. – Robinson

+1

No es lo que pediste, pero encuentro que los bloques largos de 'case' son difíciles de leer. Si necesito un alcance o cualquier otra complejidad, se obtiene un nuevo método. –

Respuesta

71

Las llaves {} se utilizan para definir un alcance para un conjunto de operaciones. Curiosamente, la siguiente compilará y trabajo:

private void ConnectionStateChange(object sender, StateChangeEventArgs e) 
{ 
    string s = "hi"; 
    switch(s) 
    { 
     case "hi": 
      { 
       int a = 1; 
       a++; 
      } 
      { 
       int a = 2; 
       a++; 
      } 
      break; 
    } 

    { 
     int a = 1; 
     a++; 
    } 
    { 
     int a = 2; 
     a++; 
    } 
} 

Como se puede ver, en la que un método que he creado cuatro variables, cada una llamada a. Cada uno está completamente separado porque, como variables locales, existen solo dentro de su propio alcance.

¿Tiene algún sentido?

+0

+1 para una demostración muy interesante. – SouthShoreAK

+0

bien explicado, realmente aprecio esto! – Wish

+55

¿Por qué extrañamente? Eso se ve bastante normal (aunque artificial). – Joey

30

Crea un nuevo ámbito en el que puede crear nuevas variables.

13

Crea un nuevo alcance para las variables que utilizó. El alcance de las variables puede ser complicado a veces. Por ejemplo, en el código que publicaste;

switch(x) 
{ 
    case(a): 
     { 
     int i = 0; 
     } 
     break; 
    case(b): 
     i = 1; // Error: The name 'i' doesn't exist in the current context 
     break; 
} 

El error tiene sentido aquí como en case(b) variables a se accede fuera de alcance. Ahora, por otro lado,

switch(x) 
{ 
    case(a): 
     { 
     int i = 0; 
     } 
     break; 
    case(b): 
     int i = 1; // Error: A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'child' scope to denote something else 
     break; 
} 

Los dos errores anteriores se ven contradictorios entre sí. Para evitar esto se debe definir el alcance por separado en ambas sentencias case,

switch(x) 
{ 
    case(a): 
     { 
     int i = 0; 
     } 
     break; 
    case(b): 
     { 
     int i = 1; // No error 
     } 
     break; 
} 

Eric Lippert compartieron una muy buena link to his blog para explicar los alcances variables en la declaración de caso. Deberías echarle un vistazo.

77

Un par de llaves (no soportes - [] - y no paréntesis - () - pero tirantes{}) con cero o más declaraciones en ellas es una declaración social en C#, y por lo tanto puede aparecer en cualquier lugar donde una declaración pueda aparecer legalmente.

Como otros han señalado, la razón típica para ello se debe a que tal declaración introduce un nuevo espacio de declaración de variables locales, que a su vez define el alcance de las variables locales declaradas dentro de ella. (Recordemos que el "alcance" de un elemento es la región de texto del programa en el que el elemento puede ser referido por su nombre no calificado.)

observo que esto es particularmente interesante en un comunicado switch porque las reglas de alcance en un cambio son un poco extrañas. Para los detalles de lo extraño, consulte la "Caso 3:" en mi artículo sobre el tema:

http://ericlippert.com/2009/08/13/four-switch-oddities/

+1

+1 para la fuente verdadera. –

+0

Siempre me ha decepcionado que C# no haya introducido una declaración de cambio más inteligente, ya que el interruptor C es una de las construcciones más extrañas y problemáticas en la programación. –

+6

@ NateC-K: C# * did * introduce una mejor declaración de cambio! Los diseñadores de C# examinaron de cerca las deficiencias de la declaración del conmutador C/C++ y la mejoraron de muchas maneras. Por ejemplo: (1) La regla de "no caer" elimina una fuente común de errores. (2) Puede activar cadenas. (3) Puede activar tipos anulables. (4) Se comprueba que los tipos de etiquetas de las cajas son compatibles con el tipo de control del interruptor. (5) "goto case 1" funciona correctamente, a diferencia de C++. Y así; en casi todas las formas concebibles, el interruptor C# es una mejora. –

Cuestiones relacionadas