Múltiples casos en la instrucción switch
¿Hay una manera de caer a través de múltiples declaraciones de casos sin declarar 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 de un lenguaje diferente, o me estoy perdiendo algo?
14 answers
No hay sintaxis en C++ ni en C# para el segundo método que mencionaste.
No hay nada malo con tu primer método. Sin embargo, si tiene rangos muy grandes, simplemente use una serie de sentencias if.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-16 02:30:06
Supongo que esto ya ha sido contestado. Sin embargo, creo que aún puedes mezclar ambas opciones de una manera sintácticamente mejor haciendo:
switch (value)
{
case 1: case 2: case 3:
// Do Something
break;
case 4: case 5: case 6:
// Do Something
break;
default:
// Do Something
break;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-03 16:01:14
Esta sintaxis es de la selección de Visual Basic ...Declaración del caso :
Dim number As Integer = 8
Select Case number
Case 1 To 5
Debug.WriteLine("Between 1 and 5, inclusive")
' The following is the only Case clause that evaluates to True.
Case 6, 7, 8
Debug.WriteLine("Between 6 and 8, inclusive")
Case Is < 1
Debug.WriteLine("Equal to 9 or 10")
Case Else
Debug.WriteLine("Not between 1 and 10, inclusive")
End Select
No puede usar esta sintaxis en C#. En su lugar, debe usar la sintaxis de su primer ejemplo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-08 12:27:57
Un poco tarde para la pregunta original, pero estoy publicando esta respuesta con la esperanza de que alguien que use una versión más reciente ( C# 7 available disponible por defecto en Visual Studio 2017/. NET Framework 4.6.2), lo encuentre útil.
En C# 7, la conmutación basada en rango ahora es posible con la instrucción switch y ayudaría con el problema del OP.
Ejemplo:
int i = 5;
switch (i)
{
case int n when (n >= 7):
Console.WriteLine($"I am 7 or above: {n}");
break;
case int n when (n >= 4 && n <= 6 ):
Console.WriteLine($"I am between 4 and 6: {n}");
break;
case int n when (n <= 3):
Console.WriteLine($"I am 3 or less: {n}");
break;
}
// Output: I am between 4 and 6: 5
Notas:
- Los paréntesis
(
y)
no son necesarios en la condiciónwhen
, pero se utilizan en este ejemplo para resaltar la(s) comparación (es). -
var
también podrá utilizarse en lugar deint
. Por ejemplo:case var n when n >= 7:
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-22 17:01:53
Puedes omitir la nueva línea que te da:
case 1: case 2: case 3:
break;
Pero considero que ese estilo es malo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-26 15:11:03
. NET Framework 3.5 tiene rangos:
Puede usarlo con "contains" y la instrucción IF, ya que como alguien dijo, la instrucción SWITCH usa el operador"==".
Aquí un ejemplo:
int c = 2;
if(Enumerable.Range(0,10).Contains(c))
DoThing();
else if(Enumerable.Range(11,20).Contains(c))
DoAnotherThing();
Pero creo que podemos divertirnos más: ya que no necesitarás los valores devueltos y esta acción no toma parámetros, ¡puedes usar acciones fácilmente!
public static void MySwitchWithEnumerable(int switchcase, int startNumber, int endNumber, Action action)
{
if(Enumerable.Range(startNumber, endNumber).Contains(switchcase))
action();
}
El antiguo ejemplo con este nuevo método:
MySwitchWithEnumerable(c, 0, 10, DoThing);
MySwitchWithEnumerable(c, 10, 20, DoAnotherThing);
Puesto que están pasando acciones, no valores, debe omitir el paréntesis, es muy importante. Si necesita una función con argumentos, simplemente cambie el tipo de Action
a Action<ParameterType>
. Si necesita valores devueltos, utilice Func<ParameterType, ReturnType>
.
En C# 3.0 no hay fácil Aplicación parcial 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, tho).
public static void MySwitchWithEnumerable(int startNumber, int endNumber, Action action){
MySwitchWithEnumerable(3, startNumber, endNumber, action);
}
Aquí un ejemplo de cómo nueva declaración importada funcional son IMHO más potente y elegante que el viejo imperativo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-30 00:37:06
@ Jennifer Owens: tienes toda la razón el siguiente código no funcionará:
case 1 | 3 | 5:
//not working do something
La única manera de hacer esto es:
case 1: case 2: case 3:
// do something
break;
El código que estás buscando funciona en visual basic donde puedes poner rangos fácilmente... en ninguna opción de interruptor o si los bloques de lo contrario conveniente, yo sugeriría, en el punto muy extremo, hacer .dll con visual basic e importar de nuevo a su proyecto de c#.
Nota: el equivalente del conmutador en visual basic es select case.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-16 13:34:54
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 en realidad no se deshace de 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...[/Edit]
switch (x)
{
case 1:
DoSomething();
break;
case 2:
DoSomething();
break;
case 3:
DoSomething();
break;
...
}
private void DoSomething()
{
...
}
Alt
switch (x)
{
case 1:
case 2:
case 3:
DoSomething();
break;
...
}
private void DoSomething()
{
...
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-16 03:30:13
Una faceta menos conocida de switch en C # es que se basa en el operador = y como puede ser anulado, podría tener algo como esto:
string s = foo();
switch (s) {
case "abc": /*...*/ break;
case "def": /*...*/ break;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-16 02:16:25
Gcc implementa una extensión al lenguaje C para soportar rangos secuenciales:
switch (value)
{
case 1...3:
//Do Something
break;
case 4...6:
//Do Something
break;
default:
//Do the Default
break;
}
Editar: Acabo de notar la etiqueta C# en la pregunta, por lo que presumiblemente una respuesta gcc no ayuda.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-16 02:59:52
En realidad no me gusta el comando GOTO también, pero está en materiales oficiales de MS, aquí están todas las sintaxis permitidas.
Si el punto final de la lista de instrucciones de una sección switch es accesible, se produce un error en tiempo de compilación. Esto se conoce como la regla de "no caer a través". El ejemplo
switch (i) {
case 0:
CaseZero();
break;
case 1:
CaseOne();
break;
default:
CaseOthers();
break;
}
Es válido porque ninguna sección de switch tiene un punto final accesible. A diferencia de C y C++, la ejecución de una sección de switch no está permitida para "caerse" a la siguiente sección de switch, y ejemplo
switch (i) {
case 0:
CaseZero();
case 1:
CaseZeroOrOne();
default:
CaseAny();
}
Resulta en un error en tiempo de compilación. Cuando la ejecución de una sección de switch va a ser seguida por la ejecución de otra sección de switch, se debe usar una sentencia explícita goto case o goto default:
switch (i) {
case 0:
CaseZero();
goto case 1;
case 1:
CaseZeroOrOne();
goto default;
default:
CaseAny();
break;
}
Se permiten varias etiquetas en una sección de conmutación. El ejemplo
switch (i) {
case 0:
CaseZero();
break;
case 1:
CaseOne();
break;
case 2:
default:
CaseTwo();
break;
}
Creo que en este caso particular, el GOTO se puede utilizar, en realidad es la única manera de caer.
Fuente: http://msdn.microsoft.com/en-us/library/aa664749%28v=vs.71%29.aspx
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-08 08:21:39
Parece que se ha puesto mucho trabajo en encontrar formas de conseguir que una de las sintaxis de C# menos utilizadas se vea mejor o funcione mejor. Personalmente me parece que la declaración switch rara vez vale la pena usar. Le sugeriría encarecidamente analizar qué datos está probando y los resultados finales que desea.
Digamos, por ejemplo, que desea probar rápidamente valores en un rango conocido para ver si son números primos. Usted quiere evitar que su código haga los cálculos derrochadores y usted puede encontrar una lista de primos en el rango que desee en línea. Podría usar una sentencia de cambio masivo para comparar cada valor con números primos conocidos.
O simplemente podría crear un mapa de matrices de primos y obtener resultados inmediatos:
bool[] Primes = new bool[] {
false, false, true, true, false, true, false,
true, false, false, false, true, false, true,
false,false,false,true,false,true,false};
private void button1_Click(object sender, EventArgs e) {
int Value = Convert.ToInt32(textBox1.Text);
if ((Value >= 0) && (Value < Primes.Length)) {
bool IsPrime = Primes[Value];
textBox2.Text = IsPrime.ToString();
}
}
Tal vez quieras ver si un carácter en una cadena es hexadecimal. Usted podría utilizar una declaración de interruptor ungly y algo grande.
O puede usar expresiones regulares para probar el char o usar la función indexOf para buscar el char en una cadena de letras hexadecimales conocidas:
private void textBox2_TextChanged(object sender, EventArgs e) {
try {
textBox1.Text = ("0123456789ABCDEFGabcdefg".IndexOf(textBox2.Text[0]) >= 0).ToString();
} catch {
}
}
Digamos que desea hacer una de 3 acciones diferentes dependiendo de un valor que será el rango de 1 a 24. Yo sugeriría el uso de 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 entonces sería utilizado para indexar en el mapa de matriz y obtener el enum de la acción que desea. A continuación, utilice un pequeño conjunto de sentencias IF o una sentencia switch 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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-23 06:25:00
Si usted tiene una cantidad muy grande de cadena (o cualquier otro tipo) Caso todos haciendo lo mismo, recomiendo el uso de una lista de cadena combinada con la cadena.Contiene la propiedad.
Así que si tienes una gran sentencia switch como esta:
switch (stringValue)
{
case "cat":
case "dog":
case "string3":
...
case "+1000 more string": //Too many string to write a case for all!
//Do something;
case "a lonely case"
//Do something else;
.
.
.
}
Es posible que desee reemplazarlo con una sentencia if como esta:
//Define all the similar "case" string in a List
List<string> listString = new List<string>(){ "cat", "dog", "string3", "+1000 more string"};
//Use string.Contains to find what you are looking for
if (listString.Contains(stringValue))
{
//Do something;
}
else
{
//Then go back to a switch statement inside the else for the remaining cases if you really need to
}
Esta escala bien para cualquier número de cadena de caso.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-29 16:00:21
Para esto, usarías una declaración goto. Tales como:
switch(value){
case 1:
goto case 3;
case 2:
goto case 3;
case 3:
DoCase123();
//This would work too, but I'm not sure if it's slower
case 4:
goto case 5;
case 5:
goto case 6;
case 6:
goto case 7;
case 7:
DoCase4567();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-09 22:41:49