Cambia caso: posso usare un intervallo invece di un numero


92

Voglio usare l'interruttore, ma ho molti casi, c'è qualche scorciatoia? Finora l'unica soluzione che conosco e ho provato è:

switch (number)
{
case 1: something; break;
case 2: other thing; break;
...
case 9: .........; break;
}

Quello che spero di essere in grado di fare è qualcosa del tipo:

switch (number)
{
case (1 to 4): do the same for all of them; break;
case (5 to 9): again, same thing for these numbers; break;
}

1
È possibile utilizzare if-else per tale scenario
Satpal

Risposte:


239

Un po 'in ritardo per il gioco per questa domanda, ma nelle recenti modifiche introdotte in C # 7 (disponibile per impostazione predefinita in Visual Studio 2017 / .NET Framework 4.6.2), la commutazione basata su intervallo è ora possibile con l' switchistruzione.

Esempio:

int i = 63;

switch (i)
{
    case int n when (n >= 100):
        Console.WriteLine($"I am 100 or above: {n}");
        break;

    case int n when (n < 100 && n >= 50 ):
        Console.WriteLine($"I am between 99 and 50: {n}");
        break;

    case int n when (n < 50):
        Console.WriteLine($"I am less than 50: {n}");
        break;
}

Appunti:

  • Le parentesi (e )non sono obbligatorie nella whencondizione, ma vengono utilizzate in questo esempio per evidenziare i confronti.
  • varpuò anche essere usato al posto di int. Ad esempio: case var n when n >= 100:.

10
Signore, sei il mio eroe. Volevo sottolinearlo con qualche parolaccia, ma piuttosto no. :)
Gawie Greef

2
La condizione (e )intorno whennon sono necessarie. Cioè case int n when n >= 100:funziona anche.
Uwe Keim

6
Anche varfunziona: Ie case var n when n >= 100:.
Uwe Keim

9
@JamesKo Penso che sia pulito e migliori la leggibilità rispetto a un mucchio di istruzioni if, in particolare se hai più di 3-4 condizioni.
Sach

1
Di gran lunga superiore a un mucchio di dichiarazioni if, è molto più pulito.
John Stock,

44

Ecco una soluzione migliore ed elegante per la tua dichiarazione del problema.

int mynumbercheck = 1000;
// Your number to be checked
var myswitch = new Dictionary <Func<int,bool>, Action>
            { 
             { x => x < 10 ,    () => //Do this!...  },  
             { x => x < 100 ,    () => //Do this!...  },
             { x => x < 1000 ,    () => //Do this!...  },
             { x => x < 10000 ,   () => //Do this!... } ,
             { x => x < 100000 ,  () => //Do this!... },
             { x => x < 1000000 ,  () => //Do this!... } 
            };

Ora per chiamare il nostro interruttore condizionale

   myswitch.First(sw => sw.Key(mynumbercheck)).Value();

Alternativo per Switch / ifElse


1
@ Akxaya Penso ancora che l'interruttore dovrebbe essere esteso in C #, ma sembra fantastico e sembra funzionare molto bene. Apprezzo davvero che tu abbia condiviso questo esempio. Grazie
WonderWorker

Questa non è una risposta chiara all'intervallo nella domanda switch / case.
Pointer Null

13
Il dizionario non memorizza e restituisce i valori nell'ordine in cui sono stati aggiunti. Questo sembra funzionare con il compilatore Microsoft, ma si potrebbe facilmente scrivere un compilatore compatibile dove non funzionava. Utilizzare invece List <KeyValuePair <Func <int, bool>, Action >>. Tieni inoltre presente che la generazione della struttura dei dati comporta un costo e quindi dovrebbe essere probabilmente un membro statico di sola lettura.
Nathan Phillips

@PointerNull: si prega di rifare il blog per il codice necessario scritto nei commenti per riferimento futuro
Akxaya

@ NathanPhillips: grazie per aver sollevato l'argomento. burbero, la collezione IList sarebbe anche un'alternativa. questo era solo un esempio che ho implementato con parametri complessi usando List <t>.
Akxaya

14

Vorrei utilizzare operatori ternari per classificare le condizioni di commutazione.

Così...

switch( number > 9 ? "High" :
        number > 5 ? "Mid" :
        number > 1 ? "Low" : "Floor")
        {
              case "High":
                    do the thing;
                    break;
               case "Mid":
                    do the other thing;
                    break;
               case "Low":
                    do something else;
                    break;
               case "Floor":
                    do whatever;
                    break;
         }

13

Per completare il thread, ecco la sintassi con C # 8:

  var percent = price switch
  {
    var n when n >= 1000000 => 7f,
    var n when n >= 900000 => 7.1f,
    var n when n >= 800000 => 7.2f,
    _ => 0f // default value
  };

Se vuoi specificare gli intervalli:

  var percent2 = price switch
  {
    var n when n >= 1000000 => 7f,
    var n when n < 1000000 && n >= 900000 => 7.1f,
    var n when n < 900000 && n >= 800000 => 7.2f,
    _ => 0f // default value
  };

8

If-else dovrebbe essere usato in quel caso, ma se c'è ancora bisogno di cambiare per qualsiasi motivo, puoi fare come sotto, i primi casi senza interruzione si propagheranno fino a quando non si incontra la prima interruzione. Come hanno suggerito le risposte precedenti, raccomando if-else over switch.

switch (number){
            case 1:
            case 2:
            case 3:
            case 4: //do something;
                    break;
            case 5:
            case 6:
            case 7:
            case 8:
            case 9: //Do some other-thing;
                   break;
        }

8

Potresti switchcostruire intervalli di "handle" usandoli insieme a uno Listdei tuoi limiti.

List<int> bounds = new List<int>() {int.MinValue, 0, 4, 9, 17, 20, int.MaxValue };

switch (bounds.IndexOf(bounds.Last(x => x < j)))
{
    case 0: // <=0
        break;

    case 1: // >= 1 and <=4
        break;
    case 2: // >= 5 and <=9
        break;
    case 3: // >= 10 and <=17
        break;
    case 4: // >= 18 and <=20
        break;

    case 5: // >20
        break;
}

Con questo approccio gli intervalli possono avere intervalli diversi.


6

L'intervallo è costante:

 int range = 5
 int newNumber = number / range;
 switch (newNumber)
 {
      case (0): //number 0 to 4
                break;
      case (1): //number 5 to 9
                break;
      case (2): //number 10 to 14
                break;
      default:  break;
 }

Altrimenti:

  if else

3

Come accennato if-elsesarebbe meglio in questo caso, dove gestirai un intervallo:

if(number >= 1 && number <= 4)
{
   //do something;
}
else if(number >= 5 && number <= 9)
{
   //do something else;
}

2

In .Net solo Visual Basic consente intervalli nelle istruzioni switch, ma in C # non esiste una sintassi valida per questo.

Affrontando il tuo problema specifico in C #, lo risolverei così:

if(number >= 1 && number <= 9) // Guard statement
{
    if(number < 5)
    {
        // Case (1 to 4):

        //break;

    }
    else
    {
        // Case (5 to 9):

        //break;

    }

}
else
{
    // Default code goes here

    //break;

}

Per illustrare ulteriormente questo aspetto, immagina di avere un valore percentuale.

Usando il tuo problema come modello, potresti desiderare che questo assomigli a:

switch (percentage)
{
    case (0 to 19):
        break;

    case (20 to 39):
        break;

    case (40 to 69):
        break;

    case (70 to 79):
        break;

    case (80 to 100):
        break;

    default:
        break;

}

Tuttavia, poiché C # non consente tale sintassi, ecco una soluzione che C # consente:

if (percentage >= 0 && percentage <= 100) // Guard statement
{
    if (percentage >= 40)
    {
        if (percentage >= 80)
        {
            // Case (80% to 100%)

            //break;

        }
        else
        {
            if (percentage >= 70)
            {
                // Case (70% to 79%)

                //break;

            }
            else
            {
                // Case (40% to 69%)

                //break;

            }

        }

    }
    else
    {
        if (percentage >= 20)
        {
            // Case (20% to 39%)

            //break;

        }
        else
        {
            // Case (0% to 19%)

            //break;

        }

    }

}
else
{
    // Default code goes here

    //break;

}

Può richiedere un po 'di tempo per abituarsi, ma va bene una volta capito.

Personalmente, accetterei con favore le dichiarazioni di switch per consentire gli intervalli.

Il futuro delle istruzioni switch C #

Ecco alcune idee che avevo su come migliorare le dichiarazioni di switch:

Versione A

switch(value)
{
    case (x => x >= 1 && x <= 4):
    break;

    case (x => x >= 5 && x <= 9):
    break;

    default:
    break;

}

Versione B

switch(param1, param2, ...)
{
    case (param1 >= 1 && param1 <= 4):
    break;

    case (param1 >= 5 && param1 <= 9 || param2 != param1):
    break;

    default:
    break;

}

1

Se utilizzi C / C ++, non esiste una sintassi "intervallo". È possibile elencare solo tutti i valori dopo ogni segmento "case". Il linguaggio Ada o Pascal supporta la sintassi dell'intervallo.


0

Prima di tutto, dovresti specificare il linguaggio di programmazione a cui ti riferisci. In secondo luogo, le switchistruzioni sono usate correttamente per insiemi chiusi di opzioni riguardanti la variabile commutata, ad esempio enumerazioni o stringhe predefinite. In questo caso, suggerirei di utilizzare la buona vecchia if-elsestruttura.


0

Attraverso switchmaiuscole e minuscole è impossibile Puoi andare con istruzioni if ​​annidate.

if(number>=1 && number<=4){
//Do something
}else if(number>=5 && number<=9){
//Do something
}

Che ne dici del buon vecchio (number >= 1 && number <= 4)invece di controllare ogni numero? Come scriveresti tra 1 e 120 ? ;-)
DarkDust

Oh, e prestare attenzione al =rispetto ==.
DarkDust

-1

Se la domanda riguardava C (non l'hai detto), la risposta è no, ma : GCC e Clang (forse altri) supportano una sintassi di intervallo , ma non è valida ISO C:

switch (number) {
    case 1 ... 4:
        // Do something.
        break;

    case 5 ... 9:
        // Do something else.
        break;
}

Assicurati di avere uno spazio prima e dopo ...altrimenti riceverai un errore di sintassi.


Pascal / delphi fa anche questo. numero di caso 1..4: fare qualcosa; ecc.
Kell

La domanda riguarda C #
SuB

@ SuB: lo so. Ho aggiunto il tag C # a questa domanda dopo che OP ci ha finalmente detto di quale lingua si tratta. Ma la risposta potrebbe ancora essere utile alle persone che vengono qui tramite un motore di ricerca, motivo per cui non l'ho cancellata.
DarkDust

-1

In C # switch case sono fondamentalmente dizionari su cosa fare dopo. Dal momento che non puoi cercare un intervallo in un dizionario, il meglio che puoi fare è il caso ... quando l'affermazione di Steve Gomez ha menzionato.


-3

Puoi usare le istruzioni if-else con || operatori (or-operator) come:

if(case1 == true || case2 == true || case3 == true)
   {
    Do this!... 
   }
else if(case4 == true || case5 == true || case6 == true)
   {
    Do this!... 
   }
else if(case7 == true || case8 == true || case9 == true)
   {
    Do this!... 
   }

Wow, è un po 'complicato per qualcosa come if (number >= 1 && number <= 4) { … } else if (number >= 5 && number <= 9) { … }, non credi?
DarkDust

Oh, va bene, sì ... Ehm, ma se le custodie che dovrebbero fare la stessa cosa non sono state ordinate, devi usare '|| operatore '...
Lukas Warsitz

Ma il suo punto era controllare se un numero è all'interno di un intervallo, quindi l'ordine non ha importanza (tranne che per gli intervalli controllati).
DarkDust

Non è una colpa , la tua soluzione non è sbagliata, è solo complicata ;-)
DarkDust

== true: face_palm: questo è il comportamento predefinito e per == false è possibile utilizzare l'operatore not
Et7f3XIV
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.