Switch case: dapatkah saya menggunakan rentang alih-alih satu angka

92

Saya ingin menggunakan sakelar, tetapi saya memiliki banyak kasus, apakah ada jalan pintas? Sejauh ini satu-satunya solusi yang saya tahu dan coba adalah:

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

Apa yang saya harap dapat saya lakukan adalah seperti:

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;
}
pengguna3022162
sumber
1
Anda dapat menggunakan if-else untuk skenario seperti itu
Satpal

Jawaban:

238

Agak terlambat untuk permainan untuk pertanyaan ini, tetapi dalam perubahan terbaru yang diperkenalkan di C # 7 (Tersedia secara default di Visual Studio 2017 / .NET Framework 4.6.2), pengalihan berbasis jangkauan sekarang dimungkinkan dengan switchpernyataan tersebut.

Contoh:

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

Catatan:

  • Tanda kurung (dan )tidak diperlukan dalam whenkondisi tersebut, tetapi digunakan dalam contoh ini untuk menyoroti perbandingan.
  • varjuga dapat digunakan sebagai pengganti int. Sebagai contoh: case var n when n >= 100:.
Steve Gomez
sumber
10
Anda tuan, adalah pahlawan saya. Saya ingin menekankan ini dengan kata-kata makian, tetapi tidak. :)
Gawie Greef
2
The (dan )sekitar whenkondisi tidak diperlukan. Yaitu case int n when n >= 100:juga bekerja.
Uwe Keim
6
Bahkan varberhasil: Yaitu case var n when n >= 100:.
Uwe Keim
9
@JamesKo Saya pikir ini bersih dan meningkatkan keterbacaan dibandingkan dengan sekumpulan pernyataan if, terutama jika Anda memiliki lebih dari 3-4 kondisi.
Sach
1
Jauh lebih unggul dari sekumpulan pernyataan if, ini jauh lebih bersih.
John Stock
44

Berikut adalah solusi yang lebih baik dan elegan untuk pernyataan masalah Anda.

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

Sekarang untuk memanggil sakelar bersyarat kami

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

Alternatif untuk Switch / ifElse

Akxaya
sumber
1
@Akxaya Saya masih berpikir peralihan harus diperpanjang di C #, tetapi ini terlihat fantastis dan tampaknya bekerja dengan sangat baik. Sangat menghargai Anda membagikan contoh ini. Terima kasih
WonderWorker
Ini bukanlah jawaban yang jelas untuk pertanyaan peralihan / kasus.
Pointer Null
13
Kamus tidak menyimpan dan mengembalikan nilai dalam urutan saat ditambahkan. Ini kebetulan bekerja dengan kompilator Microsoft, tetapi seseorang dapat dengan mudah menulis kompilator yang sesuai jika tidak berfungsi. Sebagai gantinya gunakan List <KeyValuePair <Func <int, bool>, Action >>. Ketahuilah juga bahwa ada biaya untuk membuat struktur data dan karenanya mungkin harus menjadi anggota hanya baca statis.
Nathan Phillips
@PointerNull: silakan ref blog untuk kode yang diperlukan yang ditulis dalam komentar untuk referensi di masa mendatang
Akxaya
@NathanPhillips: terima kasih telah mengungkitnya. Mantap, koleksi IList juga bisa jadi alternatif. ini hanya contoh yang saya terapkan dengan parameter kompleks menggunakan Daftar <t>.
Akxaya
14

Saya akan menggunakan operator terner untuk mengkategorikan kondisi sakelar Anda.

Begitu...

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;
         }
grafisdivine
sumber
13

Untuk melengkapi utas, berikut sintaks dengan 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
  };

Jika Anda ingin menentukan rentangnya:

  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
  };
A. Baudouin
sumber
8

If-else harus digunakan dalam kasus itu, Tetapi jika masih ada kebutuhan untuk beralih karena alasan apa pun, Anda dapat melakukan seperti di bawah ini, kasus pertama tanpa jeda akan menyebar hingga jeda pertama ditemukan. Seperti yang disarankan oleh jawaban sebelumnya, saya merekomendasikan tombol if-else over.

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;
        }
Gayathri
sumber
8

Anda bisa switchmembuat rentang "pegangan" dengan menggunakannya dalam hubungannya dengan salah Listsatu batas Anda.

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

Dengan pendekatan ini, rentang dapat memiliki rentang yang berbeda.

pengguna3598756
sumber
6

Interval konstan:

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

Jika tidak:

  if else
benba
sumber
3

Seperti yang disebutkan if-elseakan lebih baik dalam kasus ini, di mana Anda akan menangani berbagai:

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

Dalam. Net hanya Visual Basic memungkinkan rentang dalam pernyataan switch, tetapi dalam C # tidak ada sintaks yang valid untuk ini.

Mengatasi masalah spesifik Anda di C #, saya akan menyelesaikannya sebagai berikut:

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;

}

Untuk mengilustrasikan hal ini lebih lanjut, bayangkan Anda memiliki nilai persentase.

Menggunakan masalah Anda sebagai template, Anda mungkin ingin ini terlihat seperti:

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;

}

Namun, karena C # tidak mengizinkan sintaks itu, berikut adalah solusi yang diizinkan 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;

}

Mungkin perlu sedikit waktu untuk membiasakan diri, tetapi tidak apa-apa setelah Anda memahaminya.

Secara pribadi, saya akan menyambut pernyataan switch untuk memungkinkan rentang.

Masa depan pernyataan saklar C #

Berikut beberapa gagasan yang saya miliki tentang bagaimana pernyataan sakelar dapat ditingkatkan:

Versi A

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

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

    default:
    break;

}

Versi B

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

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

    default:
    break;

}
WonderWorker
sumber
1

Jika Anda menggunakan C / C ++, tidak ada sintaks "range". Anda hanya dapat mencantumkan semua nilai setelah setiap segmen "kasus". Bahasa Ada atau sintaks rentang dukungan Pascal.

SliceSort
sumber
0

Pertama-tama, Anda harus menentukan bahasa pemrograman yang Anda maksud. Kedua, switchpernyataan digunakan dengan benar untuk kumpulan opsi tertutup terkait variabel yang dialihkan, misalnya enumerasi atau string yang telah ditentukan sebelumnya. Untuk kasus ini, saya sarankan menggunakan if-elsestruktur lama yang baik .

Andrei Nicusan
sumber
0

Tidak mungkin melalui switchkasus. Anda bisa menggunakan pernyataan if bersarang.

if(number>=1 && number<=4){
//Do something
}else if(number>=5 && number<=9){
//Do something
}
Joke_Sense10
sumber
Bagaimana dengan usia tua yang baik (number >= 1 && number <= 4)daripada memeriksa setiap nomor? Bagaimana Anda akan menulis antara 1 dan 120 ? ;-)
DarkDust
Oh, dan memperhatikan =vs ==.
DarkDust
-1

Jika pertanyaannya tentang C (Anda tidak mengatakannya), maka jawabannya tidak, tetapi : GCC dan Clang (mungkin yang lain) mendukung sintaks rentang , tetapi itu bukan ISO C yang valid:

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

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

Pastikan untuk memiliki spasi sebelum dan sesudah ...atau Anda akan mendapatkan kesalahan sintaks.

DarkDust
sumber
Pascal / delphi melakukan ini juga. nomor kasus 1..4: lakukan sesuatu; dll.
Kell
Pertanyaannya adalah tentang C #
SuB
@ SuB: Saya tahu. Saya menambahkan tag C # ke pertanyaan ini setelah OP akhirnya memberi tahu kami tentang bahasa apa pertanyaan tersebut. Tetapi jawabannya mungkin masih berguna untuk orang-orang yang datang ke sini melalui mesin pencari, itulah mengapa saya belum menghapusnya.
DarkDust
-1

Dalam kasus C # switch pada dasarnya kamus tentang apa yang harus dilakukan selanjutnya. Karena Anda tidak dapat mencari rentang dalam kamus, hal terbaik yang dapat Anda lakukan adalah kasus ... ketika pernyataan Steve Gomez disebutkan.

pengguna3406087
sumber
-3

Anda bisa menggunakan pernyataan if-else dengan || operator (atau operator) seperti:

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!... 
   }
Lukas Warsitz
sumber
Wah, itu agak rumit untuk sesuatu seperti if (number >= 1 && number <= 4) { … } else if (number >= 5 && number <= 9) { … }, bukan begitu?
DarkDust
Oh baiklah ya ... Ehm tapi kalau case yang seharusnya melakukan hal yang sama tidak diperintahkan, kamu perlu menggunakan '|| operator '...
Lukas Warsitz
Tetapi intinya adalah untuk memeriksa apakah suatu angka berada dalam kisaran, jadi urutannya tidak masalah (kecuali untuk kisaran yang dicentang).
DarkDust
Ini bukan kesalahan , solusi Anda tidak salah, hanya rumit ;-)
DarkDust
== true: face_palm: ini adalah perilaku default dan untuk == false Anda tidak dapat menggunakan operator
Et7f3XIV