Question Cas multiples dans l'instruction switch


Y a-t-il un moyen de traverser plusieurs déclarations de cas sans indiquer case value: à plusieurs reprises?

Je sais que cela fonctionne:

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;
}

mais je voudrais faire quelque chose comme ça:

switch (value)
{
   case 1,2,3:
      //Do Something
      break;
   case 4,5,6:
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

Est-ce que cette syntaxe me vient d'une langue différente, ou est-ce que je manque quelque chose?


462
2017-09-16 01:34


origine


Réponses:


Il n'y a pas de syntaxe en C ++ ni C # pour la deuxième méthode que vous avez mentionnée.

Il n'y a rien de mal avec votre première méthode. Si toutefois vous avez de très grandes plages, utilisez simplement une série d'instructions if.


250
2017-09-16 01:40



Je suppose que cela a déjà été répondu. Cependant, je pense que vous pouvez encore mélanger les deux options d'une manière syntaxiquement meilleure en faisant:

switch (value)
{
case 1: case 2: case 3:          
    // Do Something
    break;
case 4: case 5: case 6: 
    // Do Something
    break;
default:
    // Do Something
    break;
}

608
2017-08-01 13:29



Cette syntaxe provient du Visual Basic Sélectionnez ... Déclaration de cas:

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

Vous ne pouvez pas utiliser cette syntaxe en C #. Au lieu de cela, vous devez utiliser la syntaxe de votre premier exemple.


63
2017-09-16 01:41



Un peu tard pour la question initiale, mais je poste cette réponse dans l’espoir que quelqu'un utilise une version plus récente (C # 7 - disponible par défaut dans Visual Studio 2017 / .NET Framework 4.6.2), le trouvera utile.

En C # 7, la commutation par plage est maintenant possible avec le changement d'instruction et aiderait avec le problème du PO.

Exemple:

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

Remarques:

  • Les parenthèses ( et ) ne sont pas requis dans le when condition, mais sont utilisés dans cet exemple pour mettre en évidence la (les) comparaison (s).
  • var peut également être utilisé à la place de int. Par exemple: case var n when n >= 7:.

30
2018-06-30 14:21



Vous pouvez laisser de côté la nouvelle ligne qui vous donne:

case 1: case 2: case 3:
   break;

mais je considère ce mauvais style.


27
2017-09-16 03:11



.NET Framework 3.5 a des plages:

Enumerable.Range de MSDN

vous pouvez l'utiliser avec "contains" et l'instruction IF, puisque comme quelqu'un a dit que l'instruction SWITCH utilise l'opérateur "==".

Voici un exemple:

int c = 2;
if(Enumerable.Range(0,10).Contains(c))
    DoThing();
else if(Enumerable.Range(11,20).Contains(c))
    DoAnotherThing();

Mais je pense que nous pouvons avoir plus de plaisir: puisque vous n'aurez pas besoin des valeurs de retour et que cette action ne prend pas de paramètres, vous pouvez facilement utiliser des actions!

public static void MySwitchWithEnumerable(int switchcase, int startNumber, int endNumber, Action action)
{
    if(Enumerable.Range(startNumber, endNumber).Contains(switchcase))
        action();
}

L'ancien exemple avec cette nouvelle méthode:

MySwitchWithEnumerable(c, 0, 10, DoThing);
MySwitchWithEnumerable(c, 10, 20, DoAnotherThing);

Puisque vous passez des actions, pas des valeurs, vous devriez omettre la parenthèse, c'est très important. Si vous avez besoin de fonctions avec des arguments, changez simplement le type de Action à Action<ParameterType>. Si vous avez besoin de valeurs de retour, utilisez Func<ParameterType, ReturnType>.

En C # 3.0 il n'y a pas de facile Application partielle pour encapsuler le fait que le paramètre case est le même, mais vous créez une petite méthode d'aide (un peu verbeux, tho).

public static void MySwitchWithEnumerable(int startNumber, int endNumber, Action action){ 
    MySwitchWithEnumerable(3, startNumber, endNumber, action); 
}

Voici un exemple de la façon dont les nouveaux états importés fonctionnels sont IMHO plus puissants et élégants que l'ancien impératif.


17
2017-09-16 10:27



@ Jennifer Owens: vous avez absolument raison le code ci-dessous ne fonctionnera pas:

case 1 | 3 | 5:
//not working do something

La seule façon de faire ceci est:

case 1: case 2: case 3:
// do something
break;

Le code que vous cherchez fonctionne sur Visual Basic, où vous pouvez facilement mettre des plages ... dans aucune option de commutateur ou si d'autres blocs pratiques, je suggérerais, au point extrême, make .dll avec visual basic et importez retour à votre projet c #.

Remarque: l'équivalent du commutateur dans Visual Basic est select case.


8
2017-11-04 00:03



Une autre option serait d'utiliser une routine. Si les cas 1-3 exécutent tous la même logique, enveloppez cette logique dans une routine et appelez-la pour chaque cas. Je sais que cela ne supprime pas réellement les déclarations de cas, mais il met en œuvre un bon style et maintient la maintenance au minimum .....

[Modifier] Ajout d'une autre implémentation pour correspondre à la question d'origine ... [/ Modifier]

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()
{
   ...
}

6
2017-09-16 03:30



Une facette moins connue de commutateur en C # est qu'il repose sur la opérateur = et comme il peut être surchargé, vous pourriez avoir quelque chose comme ceci:


string s = foo();

switch (s) {
  case "abc": /*...*/ break;
  case "def": /*...*/ break;
}

5
2017-09-16 02:16



gcc implémente une extension au langage C pour prendre en charge les plages séquentielles:

switch (value)
{
   case 1...3:
      //Do Something
      break;
   case 4...6:
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

modifier: J'ai juste remarqué la balise C # sur la question, donc une réponse gcc ne sert probablement à rien.


5
2017-09-16 02:59