Plusieurs cas dans la déclaration de commutation

Existe-t-il un moyen de traverser plusieurs déclarations de cas sans indiquer la case value: plusieurs resockets?

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 j’aimerais 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 je pense à cette syntaxe dans une autre langue ou est-ce que je manque quelque chose?

Il n’y a pas de syntaxe en C ++ ni en 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 scopes, utilisez simplement une série d’instructions if.

Je suppose que cela a déjà été répondu. Cependant, je pense que vous pouvez toujours combiner les deux options d’une manière syntaxiquement meilleure en procédant comme suit:

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

Cette syntaxe provient de Visual Basic Select … Case Statement :

 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.

Un peu tard pour la question initiale, mais je publie cette réponse dans l’espoir qu’une personne utilisant 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 basée sur la plage est désormais possible avec l’ instruction switch et pourrait aider à résoudre le problème de l’OP.

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 requirejses dans la condition when , mais sont utilisées dans cet exemple pour mettre en évidence les comparaisons.
  • var peut aussi être utilisé à la place de int . Par exemple: case var n when n >= 7:

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.

.NET Framework 3.5 a des gammes:

Enumerable.Range de MSDN

vous pouvez l’utiliser avec “contains” et l’instruction IF, car comme quelqu’un l’a dit, 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’avez pas besoin des valeurs de retour et que cette action ne prend pas de parameters, 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(); } 

Le vieil 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 d’une fonction avec des arguments, changez simplement le type d’ Action en Action . Si vous avez besoin de valeurs de retour, utilisez Func .

Dans C # 3.0, il n’existe pas d’ application partielle facile 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 verbeuse).

 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.

@ Jennifer Owens: Vous avez tout à fait raison, le code ci-dessous ne fonctionnera pas:

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

La seule façon de faire est de:

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

Le code que vous recherchez fonctionne sur Visual Basic où vous pouvez facilement mettre des gammes … dans aucune option de switch ou si autrement bloque, je suggère, à un point très extrême, de rendre .dll avec visual basic et d’importer de nouveau à votre projet c #.

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

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

Une facette moins connue de switch en C # est qu’elle repose sur l’ opérateur = et comme elle peut être remplacée, vous pouvez avoir quelque chose comme ceci:

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

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

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

Edit : Juste remarqué le tag C # sur la question, donc probablement une réponse de gcc n’aide pas.

En fait, je n’aime pas trop la commande GOTO, mais c’est dans les documents officiels de MS, voici toutes les syntaxes autorisées.

Si le point final de la liste d’instructions d’une section de commutateur est accessible, une erreur de compilation se produit. Ceci est connu comme la règle “pas de chute à travers”. L’exemple

 switch (i) { case 0: CaseZero(); break; case 1: CaseOne(); break; default: CaseOthers(); break; } 

est valide car aucune section de commutateur ne possède un sharepoint fin accessible. Contrairement à C et C ++, l’exécution d’une section de commutation n’est pas autorisée à passer à la section de commutateur suivante, et l’exemple

 switch (i) { case 0: CaseZero(); case 1: CaseZeroOrOne(); default: CaseAny(); } 

entraîne une erreur de compilation. Lorsque l’exécution d’une section de commutateur doit être suivie de l’exécution d’une autre section de commutateur, il faut utiliser une instruction goto explicite ou une instruction goto default:

 switch (i) { case 0: CaseZero(); goto case 1; case 1: CaseZeroOrOne(); goto default; default: CaseAny(); break; } 

Plusieurs étiquettes sont autorisées dans une section de commutation. L’exemple

 switch (i) { case 0: CaseZero(); break; case 1: CaseOne(); break; case 2: default: CaseTwo(); break; } 

Je crois que dans ce cas particulier, le GOTO peut être utilisé, c’est en fait le seul moyen de passer à travers.

source: http://msdn.microsoft.com/en-us/library/aa664749%28v=vs.71%29.aspx

Beaucoup de travail semble avoir été fait pour trouver des façons d’obtenir une syntaxe moins utilisée de C # ou de mieux fonctionner. Personnellement, je trouve que la déclaration de changement est rarement utile. Je suggère fortement d’parsingr les données que vous testez et les résultats finaux que vous recherchez.

Disons par exemple que vous voulez tester rapidement des valeurs dans une plage connue pour voir si elles sont des nombres premiers. Vous voulez éviter que votre code ne fasse les calculs inutiles et vous pouvez trouver une liste des nombres premiers dans la plage que vous voulez en ligne. Vous pouvez utiliser une instruction de commutation massive pour comparer chaque valeur à des nombres premiers connus.

Ou vous pourriez simplement créer une carte de tableau des nombres premiers et obtenir des résultats immédiats:

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

Peut-être que vous voulez voir si un caractère dans une chaîne est hexadécimal. Vous pouvez utiliser une instruction de changement grossièrement et un peu large.

Vous pouvez également utiliser des expressions régulières pour tester le caractère ou utiliser la fonction IndexOf pour rechercher le caractère dans une chaîne de lettres hexadécimales connues:

  private void textBox2_TextChanged(object sender, EventArgs e) { try { textBox1.Text = ("0123456789ABCDEFGabcdefg".IndexOf(textBox2.Text[0]) >= 0).ToSsortingng(); } catch { } } 

Disons que vous voulez effectuer l'une des 3 actions différentes en fonction d'une valeur comprise entre 1 et 24. Je suggère d'utiliser un ensemble d'instructions IF. Et si cela devenait trop complexe (ou si les nombres étaient plus grands, comme 5 actions différentes selon une valeur comprise entre 1 et 90), utilisez un enum pour définir les actions et créer un tableau des énumérations. La valeur serait alors utilisée pour indexer dans le tableau de tableau et obtenir l’énumération de l’action souhaitée. Utilisez ensuite un petit ensemble d'instructions IF ou une instruction switch très simple pour traiter la valeur enum résultante.

En outre, la bonne chose à propos d'une mappe de tableaux qui convertit une plage de valeurs en actions est qu'elle peut être facilement modifiée par du code. Avec le code câblé, vous ne pouvez pas facilement changer de comportement à l'exécution, mais avec une carte masortingcielle, c'est facile.

Si vous avez une très grande quantité de chaîne (ou de tout autre type). Case fait la même chose, je recommande l’utilisation d’une chaîne de caractères combinée à la chaîne ssortingng.Contains.

Donc, si vous avez un énoncé de changement important comme ceci:

 switch (ssortingngValue) { case "cat": case "dog": case "ssortingng3": ... case "+1000 more ssortingng": //Too many ssortingng to write a case for all! //Do something; case "a lonely case" //Do something else; . . . } 

Vous voudrez peut-être le remplacer par une instruction if comme celle-ci:

 //Define all the similar "case" ssortingng in a List List listSsortingng = new List(){ "cat", "dog", "ssortingng3", "+1000 more ssortingng"}; //Use ssortingng.Contains to find what you are looking for if (listSsortingng.Contains(ssortingngValue)) { //Do something; } else { //Then go back to a switch statement inside the else for the remaining cases if you really need to } 

Cette échelle bien pour n’importe quel nombre de cas de chaîne.

Pour cela, vous utiliseriez une instruction goto. Tel que:

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