it-swarm-id.com

Banyak kasus dalam pernyataan beralih

Apakah ada cara untuk melewati beberapa pernyataan kasus tanpa menyatakan case value: berulang kali?

Saya tahu ini bekerja:

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

tapi saya ingin melakukan sesuatu seperti ini:

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

Apakah ini sintaks yang saya pikirkan dari bahasa yang berbeda, atau saya kehilangan sesuatu?

524
theo

Tidak ada sintaks dalam C++ atau C # untuk metode kedua yang Anda sebutkan.

Tidak ada yang salah dengan metode pertama Anda. Namun jika Anda memiliki rentang yang sangat besar, gunakan saja serangkaian pernyataan if.

287
Brian R. Bondy

Saya kira ini sudah dijawab. Namun, saya pikir Anda masih dapat menggabungkan kedua opsi dengan cara yang lebih baik secara sintaksis dengan melakukan:

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

Sintaks ini dari Visual Basic Pilih ... Pernyataan Kasus :

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

Anda tidak dapat menggunakan sintaks ini dalam C #. Sebagai gantinya, Anda harus menggunakan sintaks dari contoh pertama Anda.

68
Neal

Agak terlambat untuk pertanyaan awal, tapi saya memposting jawaban ini dengan harapan seseorang menggunakan versi yang lebih baru ( C # 7 - tersedia secara default di Visual Studio 2017/.NET Framework 4.6 .2 ), akan sangat membantu.

Dalam C # 7, beralih berbasis jangkauan sekarang mungkin dengan pernyataan switch dan akan membantu dengan masalah OP.

Contoh:

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

Catatan:

  • Tanda kurung ( dan ) tidak diperlukan dalam kondisi when, tetapi digunakan dalam contoh ini untuk menyorot perbandingan.
  • var juga dapat digunakan sebagai pengganti int. Misalnya: case var n when n >= 7:.
47
Steve Gomez

Anda dapat meninggalkan baris baru yang memberi Anda:

case 1: case 2: case 3:
   break;

tapi saya menganggap gaya buruk itu.

31
Allan Wind

.NET Framework 3.5 telah mendapatkan rentang:

Enumerable.Range from MSDN

anda dapat menggunakannya dengan "berisi" dan pernyataan IF, karena seperti seseorang mengatakan pernyataan SWITCH menggunakan operator "==".

Berikut sebuah contoh:

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

Tapi saya pikir kita bisa bersenang-senang lagi: karena Anda tidak akan memerlukan nilai kembali dan tindakan ini tidak mengambil parameter, Anda dapat dengan mudah menggunakan tindakan!

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

Contoh lama dengan metode baru ini:

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

Karena Anda melewati tindakan, bukan nilai, Anda harus menghilangkan tanda kurung, itu sangat penting. Jika Anda membutuhkan fungsi dengan argumen, cukup ubah jenis Action menjadi Action<ParameterType>. Jika Anda perlu mengembalikan nilai, gunakan Func<ParameterType, ReturnType>.

Di C # 3.0 tidak ada yang mudah Aplikasi Parsial untuk merangkum fakta parameter kasusnya sama, tetapi Anda membuat metode pembantu kecil (sedikit verbose, tho).

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

Berikut ini contoh bagaimana pernyataan fungsional baru yang diimpor adalah IMHO lebih kuat dan elegan daripada yang imperatif lama.

18
Luca Molteni

@ Jennifer Owens: Anda memang benar kode di bawah ini tidak akan berfungsi:

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

Satu-satunya cara untuk melakukan ini adalah:

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

Kode yang Anda cari berfungsi pada visual basic di mana Anda dapat dengan mudah meletakkan rentang ... tanpa opsi untuk beralih atau jika lagi blok nyaman, saya sarankan, pada titik yang sangat ekstrim, buat .dll dengan visual basic dan impor kembali ke proyek c # Anda.

Catatan: beralih ekuivalen dalam visual basic adalah case terpilih.

8
none

Pilihan lain adalah menggunakan rutinitas. Jika case 1-3 semuanya menjalankan logika yang sama maka bungkus logika itu dalam suatu rutin dan panggil untuk setiap case. Saya tahu ini sebenarnya tidak menghilangkan pernyataan kasus, tetapi menerapkan gaya yang baik dan menjaga pemeliharaan menjadi minimum .....

[Sunting] Menambahkan implementasi alternatif untuk mencocokkan pertanyaan asli ... [/ Edit]

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

Berikut adalah solusi lengkap C # 7 ...

switch (value)
{
   case var s when new[] { 1,2,3 }.Contains(s):
      //Do Something
      break;
   case var s when new[] { 4,5,6 }.Contains(s):
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

Bekerja dengan string juga ...

switch (mystring)
{
   case var s when new[] { "Alpha","Beta","Gamma" }.Contains(s):
      //Do Something
      break;
...
}
6
Carter Medlin

gcc mengimplementasikan ekstensi ke bahasa C untuk mendukung rentang berurutan:

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

Edit: Hanya memperhatikan tag C # pada pertanyaan, jadi mungkin jawaban gcc tidak membantu.

5
DGentry

Satu sisi yang kurang diketahui dari switch di C # adalah bahwa ia bergantung pada operator = dan karena itu bisa diganti Anda dapat memiliki sesuatu seperti ini:


string s = foo();

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

Sebenarnya saya tidak suka perintah GOTO juga, tetapi ini dalam materi MS resmi, di sini semua sintaks diizinkan.

Jika titik akhir daftar pernyataan bagian switch dapat dijangkau, kesalahan waktu kompilasi terjadi. Ini dikenal sebagai aturan "no fall through". Contoh

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

valid karena tidak ada bagian sakelar yang memiliki titik akhir yang dapat dijangkau. Tidak seperti C dan C++, eksekusi bagian switch tidak diizinkan untuk "jatuh" ke bagian switch berikutnya, dan contohnya

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

menghasilkan kesalahan waktu kompilasi. Ketika eksekusi bagian switch diikuti dengan eksekusi bagian switch lain, kasus goto eksplisit atau pernyataan default goto harus digunakan:

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

Beberapa label diizinkan di bagian sakelar. Contoh

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

Saya percaya pada kasus khusus ini, GOTO dapat digunakan, itu sebenarnya satu-satunya cara untuk melakukan terobosan.

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

3
Jiří Herník

Banyak sekali pekerjaan tampaknya telah dimasukkan ke dalam mencari cara untuk mendapatkan salah satu sintaks C # paling tidak digunakan untuk entah bagaimana terlihat lebih baik atau bekerja lebih baik. Secara pribadi saya menemukan pernyataan beralih jarang layak digunakan. Saya sangat menyarankan untuk menganalisis data apa yang Anda uji dan hasil akhir yang Anda inginkan.

Misalnya, Anda ingin menguji nilai dengan cepat dalam rentang yang diketahui untuk melihat apakah itu bilangan prima. Anda ingin menghindari kode Anda melakukan perhitungan boros dan Anda dapat menemukan daftar bilangan prima dalam rentang yang Anda inginkan online. Anda bisa menggunakan pernyataan peralihan besar-besaran untuk membandingkan setiap nilai dengan bilangan prima yang diketahui.

Atau Anda bisa saja membuat peta array bilangan prima dan mendapatkan hasil langsung:

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

Mungkin Anda ingin melihat apakah karakter dalam string adalah heksadesimal. Anda bisa menggunakan statement switch yang jelek dan agak besar.

Atau Anda bisa menggunakan ekspresi reguler untuk menguji char atau menggunakan fungsi IndexOf untuk mencari char dalam serangkaian huruf heksadesimal yang diketahui:

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

Katakanlah Anda ingin melakukan salah satu dari 3 tindakan berbeda tergantung pada nilai yang akan menjadi kisaran 1 hingga 24. Saya akan menyarankan menggunakan seperangkat pernyataan IF. Dan jika itu menjadi terlalu kompleks (Atau angkanya lebih besar seperti 5 tindakan yang berbeda tergantung pada nilai dalam kisaran 1 hingga 90) maka gunakan enum untuk menentukan tindakan dan membuat peta susunan enum. Nilai tersebut kemudian akan digunakan untuk mengindeks ke dalam array map dan mendapatkan enum dari tindakan yang Anda inginkan. Kemudian gunakan baik set kecil pernyataan IF atau pernyataan beralih yang sangat sederhana untuk memproses nilai enum yang dihasilkan.

Juga, hal yang menyenangkan tentang peta array yang mengubah berbagai nilai menjadi tindakan adalah bahwa hal itu dapat dengan mudah diubah oleh kode. Dengan kode berkabel, Anda tidak dapat dengan mudah mengubah perilaku saat runtime tetapi dengan peta larik itu mudah.

2
Darin

Jika Anda memiliki jumlah string yang sangat besar (atau tipe lainnya) Jika semuanya melakukan hal yang sama, saya merekomendasikan penggunaan Daftar string yang dikombinasikan dengan string. Properti berisi.

Jadi, jika Anda memiliki pernyataan beralih besar seperti:

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

Anda mungkin ingin menggantinya dengan pernyataan if seperti ini:

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

Skala ini baik untuk sejumlah kasus tali.

1
Maxter