2010-06-24 10 views
82

Cuando creo un comunicado switch en VS2008 C# como esta (artificial):¿Por qué C# se rompe si no es opcional?

switch (state) { 
    case '1': 
     state = '2'; 
    case '2': 
     state = '1'; 
} 

se queja de que no estoy autorizado a caer a través de:

de control no puede caer a través de una etiqueta de la caja ('caso '1'(0x31):') a otro

Si no se le permite caer a través, entonces ¿cuál es el propósito de la declaración break en absoluto? ¿Por qué los diseñadores de idiomas no lo dejaron de lado y saltaron automáticamente al final de la declaración switch en lugar de forzarnos a colocar una construcción innecesaria?

Respuesta

68

De la boca del caballo (MSDN) Why is the C# switch statement designed to not allow fall-through, but still require a break?.

Citando los bits más destacadas, es por eso que no permiten caída a través de:

Este comportamiento implícito de paso al siguiente se utiliza a menudo para reducir la cantidad de código necesario y, a menudo no es un problema la primera vez que se escribe ese código Sin embargo, a medida que el código pasa de la fase de desarrollo inicial a la fase de mantenimiento, el código anterior puede generar errores sutiles que son muy difíciles de depurar. Estos errores son el resultado del error muy común del desarrollador al agregar un caso, pero olvidando poner un descanso al final del bloque.

En C#, la instrucción switch requiere que el control de flujo explícito ocurra al final de un caso, ya sea un break, goto, return o throw. Si el desarrollador desea una semántica fallida, puede lograrse mediante un goto explícito al final de una declaración de caso.

Y es por esto que no es automática:

Como resultado de las reglas de C# que requieren explícitamente el control de flujo a ocurrir al final de un bloque de caso (la mayoría por lo general un descanso), muchas personas pregunta por qué el comportamiento simplemente no se modificó de manera tal que no se produjo el fracaso. Es decir, no haga que se requiera descanso, simplemente cambie la semántica del interruptor para no tener fallas en los casos. La razón por la que esto no se hizo fue para que los desarrolladores que estaban muy acostumbrados a C++ no tuvieran dificultades para entender lo que estaba haciendo una declaración de cambio.

+0

El enlace ya no está activo. –

+1

http://web.archive.org/web/20110515005800/http://msdn.microsoft.com/en-us/vcsharp/aa336815.aspx –

+3

Y ahora, 7 lágrimas después de que esto fue escrito, vemos cuán tonta es esta decisión estaba. Ahora estamos introduciendo la coincidencia de patrones, un nuevo concepto al que deciden co-optar por la sintaxis 'switch' y que ahora está atascado por una decisión tomada a" programadores de C++ no confusos hace 2 décadas ". No es la mejor opción, equipo de C#. –

12

Si usted no tiene ningún código en el caso 1, se le permite caer a través de, por lo que se puede decir que "todos estos casos comparten este pedazo de código"

+0

Pero en ese caso no recibirá una advertencia. El compilador te advierte sobre algo que puede inferir. – Kobi

79

Básicamente para que sea más familiar para Desarrolladores C/C++/Java. Personalmente creo que fue un error, pero ese es el razonamiento.

yo hubiera preferido un bloque forzada:

case '1': 
{ 
} 

Aparte de cualquier otra cosa, que habría evitado las situaciones de alcance variables extrañas para switch/case. Aún se podía tener múltiples etiquetas caso, por supuesto:

case '0': 
case '1': 
{ 
} 

También podría ser agradable ser capaz de enumerar varios casos más simplemente:

case '0', '1': 
{ 
} 

Ah, y un ligero hilar fino sobre su descripción del idioma existente: no tiene tiene para tener un descanso. Es solo que el final del caso tiene que ser inalcanzable. También puede tener throw, goto o return. Puede haber otros que he echado de menos :)

+2

@Jon +1 - ¡Nunca pensé que podrías hacer eso! – GenericTypeTea

+0

@GenericTypeTea: ¿Qué parte? –

+0

Creo que es una buena decisión no hacer que las construcciones de aspecto idéntico se comporten de manera diferente. Eso sería un infierno para los programadores que tienen que cambiar de idioma con frecuencia. –

35

Se le permite caer a través, pero hay que hacerlo de forma explícita con el goto palabra clave:

switch (state) { 
    case '1': 
     state = '2'; 
     goto case '2'; 
    case '2': 
     state = '1'; 
     break; 
} 

Puede break o goto en C#, pero lo que no puedes hacer es no indicar cuál quieres, porque esa es una fuente potencial de errores difíciles de detectar.

Es mucho más fácil detectar que su código dice goto cuando quería break (o viceversa) que señalar que olvidó agregar cualquiera.

Puede sonar estúpido, pero muchas búsquedas cansadas de dos horas para la causa de un error de C++ terminan en una repentina comprensión de que olvidó agregar un break y su código está cayendo todo el tiempo. C# lo evita al forzarte a decir lo que quieres.

+2

Estoy avergonzado de que no sabía que podías 'continuar'.Solo pensé que era ilegal evitar todos los errores fallidos ... Gracias :) – simendsjo

+3

¿Has probado este código? No compila Sin embargo, puedes hacer "goto case" 2 '". –

+0

Me da "Ningún bucle adjunto para romper o continuar" –

Cuestiones relacionadas