Przypadek przełącznika: czy mogę użyć zakresu zamiast jednej liczby


86

Chcę użyć przełącznika, ale mam wiele przypadków, czy jest jakiś skrót? Jak dotąd jedynym rozwiązaniem, które znam i wypróbowałem, jest:

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

Mam nadzieję, że jestem w stanie zrobić coś takiego:

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
Możesz użyć if-else dla takiego scenariusza
Satpal

Odpowiedzi:


226

Trochę za późno na to pytanie, ale w ostatnich zmianach wprowadzonych w C # 7 (domyślnie dostępne w programie Visual Studio 2017 / .NET Framework 4.6.2), przełączanie na podstawie zakresu jest teraz możliwe za pomocą switchinstrukcji.

Przykład:

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

Uwagi:

  • Nawiasy (i )nie są wymagane w whenwarunku, ale są używane w tym przykładzie do wyróżnienia porównań.
  • varmoże być również używany zamiast int. Na przykład: case var n when n >= 100:.

10
Panie, jesteś moim bohaterem. Chciałem to podkreślić jakimś przekleństwem, ale raczej nie. :)
Gawie Greef

2
Stan (i )okolice whensą niepotrzebne. To znaczy case int n when n >= 100:też działa.
Uwe Keim

6
Nawet vardziała: tj case var n when n >= 100:.
Uwe Keim

9
@JamesKo Myślę, że jest czysty i poprawia czytelność w porównaniu z zestawem instrukcji if, szczególnie jeśli masz więcej niż 3-4 warunki.
Sach

1
Znacznie lepszy od zestawu instrukcji if, jest znacznie czystszy.
John Stock

44

Oto lepsze i eleganckie rozwiązanie problemu.

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

Teraz nazwijmy nasz przełącznik warunkowy

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

Alternatywa dla Switch / ifElse


1
@Akxaya Nadal uważam, że przełącznik powinien być rozszerzony w C #, ale wygląda to fantastycznie i wydaje się działać naprawdę dobrze. Naprawdę doceniam udostępnienie tego przykładu. Dziękuję
WonderWorker

To nie jest jasna odpowiedź na pytanie dotyczące zakresu w przypadku przełącznika / przypadku.
Pointer Null

13
Słownik nie przechowuje i nie zwraca wartości w kolejności, w jakiej zostały dodane. Dzieje się tak z kompilatorem firmy Microsoft, ale można łatwo napisać kompatybilny kompilator, w którym nie działa. Zamiast tego użyj List <KeyValuePair <Func <int, bool>, Action >>. Należy również pamiętać, że generowanie struktury danych wiąże się z kosztami, dlatego prawdopodobnie powinien to być statyczny element członkowski tylko do odczytu.
Nathan Phillips

@PointerNull: proszę odnieść się do bloga, aby znaleźć potrzebny kod napisany w komentarzach do wykorzystania w przyszłości
Akxaya

@NathanPhillips: dziękuję za omówienie tego. oczywiście, kolekcja IList byłaby również alternatywą. to był tylko przykład, który zaimplementowałem ze złożonymi parametrami przy użyciu List <t>.
Akxaya,

13

Użyłbym operatorów trójskładnikowych do kategoryzowania warunków przełącznika.

Więc...

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

12

Aby zakończyć wątek, oto składnia z 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
  };

Jeśli chcesz określić zakresy:

  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

Jeśli w takim przypadku powinno być użyte-else, ale jeśli nadal istnieje potrzeba przełączenia z jakiegokolwiek powodu, możesz zrobić jak poniżej, pierwsze przypadki bez przerwy będą propagowane do napotkania pierwszej przerwy. Jak sugerowały poprzednie odpowiedzi, polecam przełącznik if-else.

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

Możesz switchskonstruować zakresy „uchwytów”, używając go w połączeniu z a Listz twoich granic.

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

Przy takim podejściu zakresy mogą mieć różne rozpiętości.


6

Interwał jest stały:

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

Inaczej:

  if else

3

Jak wspomniano, if-elsebyłoby lepiej w tym przypadku, gdy będziesz obsługiwał zakres:

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

2

W .Net tylko Visual Basic zezwala na zakresy w instrukcjach przełącznika, ale w języku C # nie ma prawidłowej składni.

Rozwiązując twój konkretny problem w C #, rozwiązałbym go w ten sposób:

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;

}

Aby to dalej zilustrować, wyobraź sobie, że masz wartość procentową.

Używając swojego problemu jako szablonu, możesz chcieć, aby wyglądało to następująco:

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;

}

Jednak ponieważ C # nie zezwala na taką składnię, oto rozwiązanie, na które pozwala C #:

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;

}

Przyzwyczajenie się do tego może trochę potrwać, ale jak już to zrobisz, będzie dobrze.

Osobiście z zadowoleniem przyjąłbym instrukcje przełączania, które pozwalają na zakresy.

Przyszłość instrukcji przełączania języka C #

Oto kilka pomysłów na to, jak można ulepszyć instrukcje przełączania:

Wersja A

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

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

    default:
    break;

}

Wersja B

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

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

    default:
    break;

}

1

Jeśli używasz C / C ++, nie ma składni „zakresu”. Możesz podać tylko wszystkie wartości po każdym segmencie „przypadku”. Składnia zakresu obsługi języka Ada lub Pascal.


0

Przede wszystkim powinieneś określić język programowania, do którego się odnosisz. Druga,switch instrukcje są właściwie używane dla zamkniętych zestawów opcji dotyczących zmiennej przełączanej, np. Wyliczeń lub predefiniowanych łańcuchów. W tym przypadku sugerowałbym użycie starej dobrej if-elsestruktury.


0

Przez switchprzypadek jest to niemożliwe. Możesz przejść z zagnieżdżonymi instrukcjami if.

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

A co z dobrym starym (number >= 1 && number <= 4)zamiast sprawdzania każdej liczby? Jak byś napisał od 1 do 120 ? ;-)
DarkDust

Och, i zwracać uwagę na =porównaniu ==.
DarkDust

-1

Jeśli pytanie dotyczyło C (nie powiedziałeś), to odpowiedź brzmi nie, ale : GCC i Clang (może inni) obsługują składnię zakresu , ale nie jest to poprawne ISO C:

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

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

Upewnij się, że masz spację przed i po, w ...przeciwnym razie pojawi się błąd składni.


Pascal / delphi też to robi. numer sprawy 1..4: zrób coś; itd.
Kell

Pytanie dotyczy C #
SuB

@SuB: Wiem. Dodałem tag C # do tego pytania po tym, jak OP w końcu powiedział nam, jakiego języka dotyczy pytanie. Ale odpowiedź może nadal być przydatna dla osób, które przychodzą tutaj przez wyszukiwarkę, dlatego jej nie usunąłem.
DarkDust

-1

W C # przypadkach przełączników są w zasadzie słownikami, co robić dalej. Ponieważ nie możesz wyszukać zakresu w słowniku, najlepsze, co możesz zrobić, to przypadek ... gdy wspomniał o stwierdzeniu Steve Gomez.


-3

Możesz używać instrukcji if-else z || operatory (lub-operator), takie jak:

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, to trochę skomplikowane jak na coś takiego if (number >= 1 && number <= 4) { … } else if (number >= 5 && number <= 9) { … }, nie sądzisz?
DarkDust

W porządku, tak ... Ehm, ale jeśli skrzynki, które mają robić to samo, nie są uporządkowane, musisz użyć '|| operator '...
Lukas Warsitz 22.11.13

Chodziło mu jednak o sprawdzenie, czy liczba mieści się w zakresie, więc kolejność nie ma znaczenia (z wyjątkiem sprawdzonych zakresów ).
DarkDust

To nie wina , twoje rozwiązanie nie jest złe, tylko skomplikowane ;-)
DarkDust

== true: face_palm: jest to domyślne zachowanie i dla == false możesz użyć operatora not
Et7f3XIV
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.