¿Hay alguna manera de pasar por múltiples declaraciones de casos sin indicarlo case value:
repetidamente?
Sé que esto funciona:
switch (value)
{
case 1:
case 2:
case 3:
// Do some stuff
break;
case 4:
case 5:
case 6:
// Do some different stuff
break;
default:
// Default stuff
break;
}
pero me gustaría hacer algo como esto:
switch (value)
{
case 1,2,3:
// Do something
break;
case 4,5,6:
// Do something
break;
default:
// Do the Default
break;
}
¿Es esta sintaxis en la que estoy pensando en un idioma diferente o me falta algo?
c#
switch-statement
theo
fuente
fuente
,
y uno que no se comparte con ningún otro lenguaje de estilo C. Eso me parecería mucho más sucio.Respuestas:
No hay sintaxis en C ++ ni C # para el segundo método que mencionó.
No hay nada malo con tu primer método. Sin embargo, si tiene rangos muy grandes, simplemente use una serie de declaraciones if.
fuente
Supongo que esto ya ha sido respondido. Sin embargo, creo que aún puede mezclar ambas opciones de una manera sintácticamente mejor haciendo:
fuente
Esta sintaxis es de Visual Basic Select ... Declaración de caso :
No puede usar esta sintaxis en C #. En su lugar, debe usar la sintaxis de su primer ejemplo.
fuente
En C # 7 (disponible de forma predeterminada en Visual Studio 2017 / .NET Framework 4.6.2), el cambio basado en rango ahora es posible con la declaración de cambio y ayudaría con el problema del OP.
Ejemplo:
Notas:
(
y)
no son obligatorios en lawhen
condición, pero se usan en este ejemplo para resaltar las comparaciones.var
también se puede usar en lugar deint
. Por ejemplo:case var n when n >= 7:
.fuente
Puede omitir la nueva línea que le brinda:
pero considero ese mal estilo.
fuente
.NET Framework 3.5 tiene rangos:
Enumerable Rango desde MSDN
puede usarlo con "contiene" y la instrucción IF, ya que, como alguien dijo, la instrucción SWITCH utiliza el operador "==".
Aquí un ejemplo:
Pero creo que podemos divertirnos más: como no necesitará los valores de retorno y esta acción no toma parámetros, ¡puede usar acciones fácilmente!
El viejo ejemplo con este nuevo método:
Como estás pasando acciones, no valores, debes omitir el paréntesis, es muy importante. Si necesita una función con argumentos, simplemente cambie el tipo de
Action
aAction<ParameterType>
. Si necesita valores de retorno, useFunc<ParameterType, ReturnType>
.En C # 3.0 no hay una aplicación parcial fácil para encapsular el hecho de que el parámetro case es el mismo, pero se crea un pequeño método auxiliar (un poco detallado).
Aquí un ejemplo de cómo las nuevas declaraciones funcionales importadas son, en mi humilde opinión, más poderosas y elegantes que la antigua imperativa.
fuente
int start
yint count
. Sus ejemplos no funcionarán correctamente tal como fueron escritos. Lo escribes como si el segundo argumento esint end
. Por ejemplo,Enumerable.Range(11,20)
daría como resultado 20 números que comienzan con 11, y no números del 11 al 20.Enumerable.Range(11,20).Contains(c)
es equivalente afor(int i = 11; i < 21; ++i){ if (i == c) return true; } return false;
Si tuviera un rango grande, tomaría mucho tiempo, mientras lo usa>
y<
sería rápido y de tiempo constante.MySwitchWithEnumerable
retornovoid
es un diseño débil para esta situación. RAZÓN: Has convertidoif-else
una serie de declaraciones independientes, que oculta la intención, que es que son mutuamente excluyentes, soloaction
se ejecuta una. En vez de regresobool
, con el cuerpoif (..) { action(); return true; } else return false;
El sitio de llamar a continuación, muestra la intención:if (MySwitchWithEnumerable(..)) else (MySwitchWithEnumerable(..));
. Esto es preferible. Sin embargo, ya no es una mejora significativa sobre su versión original, para este caso simple.Aquí está la solución completa de C # 7 ...
Funciona con cadenas también ...
fuente
El siguiente código no funcionará:
La única forma de hacer esto es:
El código que está buscando funciona en Visual Basic, donde puede colocar fácilmente rangos ... en la
none
opción de laswitch
instrucción oif else
bloques convenientes, sugeriría, en un punto muy extremo, hacer .dll con Visual Basic e importar de nuevo a su proyecto C #.Nota: el equivalente de conmutador en Visual Basic es
Select Case
.fuente
Otra opción sería usar una rutina. Si todos los casos 1-3 ejecutan la misma lógica, envuelva esa lógica en una rutina y llámela para cada caso. Sé que esto realmente no elimina las declaraciones de casos, pero implementa un buen estilo y mantiene el mantenimiento al mínimo .....
[Editar] Se agregó una implementación alternativa para que coincida con la pregunta original ... [/ Editar]
Alt
fuente
Una faceta menos conocida del interruptor en C # es que se basa en el operador = y dado que se puede anular, podría tener algo como esto:
fuente
gcc implementa una extensión del lenguaje C para admitir rangos secuenciales:
Editar : Acabo de notar la etiqueta C # en la pregunta, por lo que presumiblemente una respuesta gcc no ayuda.
fuente
En C # 7 ahora tenemos Pattern Matching para que pueda hacer algo como:
fuente
En realidad, tampoco me gusta el comando GOTO, pero está en los materiales oficiales de Microsoft, y aquí están todas las sintaxis permitidas.
Si se puede alcanzar el punto final de la lista de instrucciones de una sección de conmutador, se produce un error en tiempo de compilación. Esto se conoce como la regla de "no caerse". El ejemplo
es válido porque ninguna sección del interruptor tiene un punto final alcanzable. A diferencia de C y C ++, la ejecución de una sección de cambio no está permitida para "pasar por alto" a la siguiente sección de cambio, y el ejemplo
da como resultado un error en tiempo de compilación. Cuando la ejecución de una sección de cambio va a ser seguida por la ejecución de otra sección de cambio, se debe usar un caso de goto explícito o una declaración predeterminada de goto:
Se permiten múltiples etiquetas en una sección de interruptor. El ejemplo
Creo que en este caso particular, se puede usar GOTO, y en realidad es la única forma de fracasar.
Fuente: http://msdn.microsoft.com/en-us/library/aa664749%28v=vs.71%29.aspx
fuente
goto
casi siempre se puede evitar (aunque no lo considero "terrible" aquí, está cumpliendo un rol específico y estructurado). En su ejemplo, debido a que ha envuelto los cuerpos de los casos en funciones (algo bueno), el caso 0 puede convertirseCaseZero(); CaseZeroOrOne(); break;
. No segoto
requiereParece que se ha realizado una gran cantidad de trabajo para encontrar formas de obtener una de las sintaxis menos utilizadas de C # para que parezca mejor o funcione mejor. Personalmente, creo que la declaración de cambio rara vez vale la pena usarla. Sugeriría encarecidamente analizar qué datos está probando y los resultados finales que desea.
Digamos, por ejemplo, que desea probar rápidamente los valores en un rango conocido para ver si son números primos. Desea evitar que su código haga los cálculos innecesarios y puede encontrar una lista de números primos en el rango que desea en línea. Podría usar una declaración de cambio masivo para comparar cada valor con números primos conocidos.
O simplemente podría crear un mapa de matriz de números primos y obtener resultados inmediatos:
Tal vez quiera ver si un carácter en una cadena es hexadecimal. Podría usar una declaración de cambio fea y algo grande.
O puede usar expresiones regulares para probar el carácter o utilizar la función IndexOf para buscar el carácter en una cadena de letras hexadecimales conocidas:
Digamos que desea realizar una de 3 acciones diferentes dependiendo de un valor que será el rango de 1 a 24. Sugeriría usar un conjunto de declaraciones IF. Y si eso se volvió demasiado complejo (o los números eran más grandes, como 5 acciones diferentes dependiendo de un valor en el rango de 1 a 90), use una enumeración para definir las acciones y crear un mapa de matriz de las enumeraciones. El valor se usaría para indexar en el mapa de matriz y obtener la enumeración de la acción que desea. Luego use un pequeño conjunto de declaraciones IF o una declaración de cambio muy simple para procesar el valor de enumeración resultante.
Además, lo bueno de un mapa de matriz que convierte un rango de valores en acciones es que se puede cambiar fácilmente por código. Con el código cableado no puede cambiar fácilmente el comportamiento en tiempo de ejecución, pero con un mapa de matriz es fácil.
fuente
Solo para agregar a la conversación, usando .NET 4.6.2 También pude hacer lo siguiente. Probé el código y funcionó para mí.
También puede hacer varias declaraciones "OR", como a continuación:
También puede verificar si coincide con un valor en una matriz:
fuente
Si tiene una gran cantidad de cadenas (o de cualquier otro tipo) en el caso de que todas hagan lo mismo, recomiendo el uso de una lista de cadenas combinada con la cadena. Contiene la propiedad.
Entonces, si tiene una declaración de cambio grande como esta:
Es posible que desee reemplazarlo con una
if
declaración como esta:Esto escala bien para cualquier número de casos de cadena.
fuente
Creo que este es mejor en C # 7 o superior.
También puede marcar Rango en la caja del interruptor C #: Caja del interruptor: ¿puedo usar un rango en lugar de un número? O si desea comprender los conceptos básicos de la caja del interruptor C #
fuente
Para esto, usarías una declaración goto. Como:
fuente
goto
. Peor aún, es un uso completamente innecesariogoto
, ya que la sintaxis original establecida por OP funciona. La pregunta era si había una forma más concisa de dar los casos alternativos. Como la gente respondió años antes que usted , sí, si está dispuesto a poner varios casos en una líneacase 1: case 2:
, y si el estilo automático del editor lo permite.