Haruskah beralih pernyataan selalu mengandung klausa default?


255

Dalam salah satu ulasan kode pertama saya (beberapa waktu lalu), saya diberitahu bahwa praktik yang baik untuk memasukkan klausa default di semua pernyataan switch. Saya baru-baru ini mengingat nasihat ini tetapi tidak ingat apa itu pembenaran. Kedengarannya aneh bagi saya sekarang.

  1. Apakah ada alasan yang masuk akal untuk selalu menyertakan pernyataan default?

  2. Apakah bahasa ini tergantung? Saya tidak ingat bahasa apa yang saya gunakan saat itu - mungkin ini berlaku untuk beberapa bahasa dan tidak untuk yang lain?


9
Ini akan menjadi tergantung pada bahasa sebagian besar
skaffman

Jawaban:


277

Switch case hampir selalu memiliki defaultcase.

Alasan menggunakan a default

1. Untuk 'menangkap' nilai yang tidak terduga

switch(type)
{
    case 1:
        //something
    case 2:
        //something else
    default:
        // unknown type! based on the language,
        // there should probably be some error-handling
        // here, maybe an exception
}

2. Untuk menangani tindakan 'default', di mana kasing adalah untuk perilaku khusus.

Anda melihat ini BANYAK dalam program berbasis menu dan skrip bash shell. Anda mungkin juga melihat ini ketika sebuah variabel dideklarasikan di luar switch-case tetapi tidak diinisialisasi, dan setiap case menginisialisasi ke sesuatu yang berbeda. Di sini standar perlu menginisialisasi juga sehingga kode baris yang mengakses variabel tidak menimbulkan kesalahan.

3. Untuk menunjukkan kepada seseorang yang membaca kode Anda bahwa Anda telah membahas kasus itu.

variable = (variable == "value") ? 1 : 2;
switch(variable)
{
    case 1:
        // something
    case 2:
        // something else
    default:
        // will NOT execute because of the line preceding the switch.
}

Ini adalah contoh yang terlalu disederhanakan, tetapi intinya adalah bahwa seseorang yang membaca kode seharusnya tidak bertanya-tanya mengapa variabletidak bisa menjadi sesuatu selain 1 atau 2.


Satu-satunya kasus yang dapat saya pikirkan untuk TIDAK digunakan defaultadalah ketika saklar memeriksa sesuatu yang agak jelas setiap alternatif lain dapat dengan senang hati diabaikan

switch(keystroke)
{
    case 'w':
        // move up
    case 'a':
        // move left
    case 's':
        // move down
    case 'd':
        // move right
    // no default really required here
}

26
Contoh Anda mengenai penekanan tombol agak bertentangan dengan apa yang baru saja Anda katakan. : | Saya pikir sedikit penjelasan lebih masuk akal seperti: Anda tidak peduli tentang default dalam hal ini karena jika tombol lain ditekan Anda tidak peduli, tetapi jika variabel yang dikirimkan berbeda dari yang diharapkan, kami peduli .
Andrew

1
Pada saat yang sama jika Anda memeriksa parameter GET, Anda mungkin tidak ingin pengecualian dilemparkan setiap kali pengguna mengubah url dapatkan ke sesuatu yang tidak valid: [
Andrew

4
@Andrew WASD biasa digunakan untuk pergerakan karakter permainan komputer. Anda tidak akan memerlukan tindakan default karena tombol lain dapat ditetapkan untuk interaksi lainnya. Dalam jenis saklar ini, ada baiknya memanggil fungsi gerakan.
jemiloii

13
Beberapa kompiler memperingatkan ketika menyalakan enum jika suatu kasus tidak terjawab, dan menambahkan kasing standar akan menekan peringatan itu. Mengingat bahwa ini dalam pengalaman saya sumber kesalahan yang sangat umum (lupa memperbarui sakelar di suatu tempat setelah nilai enum ditambahkan), ini sepertinya alasan yang sangat bagus untuk menghilangkan case default.
rdb

3
@ Virusrocks Jika kondisi Anda adalah enum, Anda masih dapat memiliki nilai yang tidak terduga. Misalnya, jika Anda menambahkan nilai baru ke enum, dan lupa memperbarui sakelar. Juga, dalam beberapa bahasa Anda dapat menetapkan nilai integer ke enum. Dalam C ++ enum MyEnum { FOO = 0, BAR = 1 }; MyEnum value = (MyEnum)2;membuat MyEnuminstance yang valid yang tidak sama dengan FOOatau BAR. Jika salah satu dari masalah ini akan menyebabkan kesalahan dalam proyek Anda, kasus default akan membantu Anda menemukan kesalahan dengan sangat cepat, seringkali tanpa perlu debugger!
cdgraham

54

Tidak.

Bagaimana jika tidak ada tindakan default, konteks penting. Bagaimana jika Anda hanya peduli untuk bertindak berdasarkan beberapa nilai?

Ambil contoh membaca penekanan tombol untuk gim

switch(a)
{
   case 'w':
     // Move Up
     break;
   case 's':
     // Move Down
     break;
   case 'a':
     // Move Left
     break;
   case 'd':
     // Move Right
     break;
}

Menambahkan:

default: // Do nothing

Hanya buang-buang waktu dan menambah kompleksitas kode tanpa alasan.


14
Contoh yang baik. Tetapi pada kenyataannya, menambahkan klausa default dengan // do nothingkomentar sederhana membuat jelas bahwa itu 'ok' jika tidak semua kasus dicakup, sebagai lawan dari pernyataan switch lainnya di mana ini akan menjadi 'tidak ok'.
The Nail

8
Tidak. Pengkodean tidak hanya menangani beberapa kasus. Juga berfungsi sebagai dokumen. Dengan menulis default: dan berkomentar seperti // Tidak melakukan apa-apa atau sesuatu yang lain, keterbacaan kode menjadi lebih baik.
JongAm Park

22
Tidak setuju dengan komentar lainnya. Menambahkan default // Jangan lakukan apa-apa menambahkan sangat sedikit kecuali Anda tidak tahu cara kerja kode. Saya dapat melihat pernyataan switch tanpa default dan tahu bahwa defaultnya adalah tidak melakukan apa-apa. Menambahkan kekacauan tidak membuat ini lebih jelas.
Robert Noack

Persis. Itu dalam konsep yang sama dalam menyerahkan par post al. Anda menangani yang Anda pedulikan bukan yang lain.
Jimmy Kane

2
@ jybrd Jika Anda tidak percaya bahwa pengembang sebelumnya sengaja mengabaikan default, mengapa Anda percaya bahwa mereka benar memasukkannya? Default bisa kosong tanpa sengaja semudah sama sekali hilang. Sebuah komentar tidak diperlukan untuk sesuatu yang sepele. Ini adalah kekacauan kode. Tulis tes unit cakupan penuh untuk menunjukkan niat Anda sebagai gantinya. (Hanya pendapat saya)
Robert Noack

45

TIDAK memiliki kasing yang sebenarnya dapat bermanfaat dalam beberapa situasi.

Jika sakelar Anda adalah nilai enum, dengan tidak memiliki kasing default, Anda bisa mendapatkan peringatan kompilator jika Anda kehilangan kasing apa pun. Dengan begitu, jika nilai enum baru ditambahkan di masa mendatang dan Anda lupa menambahkan case untuk nilai-nilai ini di sakelar, Anda bisa mencari tahu tentang masalah pada waktu kompilasi. Anda harus tetap memastikan kode mengambil tindakan yang sesuai untuk nilai yang tidak ditangani, jika nilai yang tidak valid dilemparkan ke jenis enum. Jadi ini mungkin bekerja paling baik untuk kasus-kasus sederhana di mana Anda dapat kembali dalam kasus enum daripada istirahat.

enum SomeEnum
{
    ENUM_1,
    ENUM_2,
    // More ENUM values may be added in future
};

int foo(SomeEnum value)
{
    switch (value)
    {
    case ENUM_1:
        return 1;
    case ENUM_2:
        return 2;
    }
    // handle invalid values here
    return 0;
 }

Ini pengamatan penting! Itu berlaku bahkan lebih di Jawa karena tidak memungkinkan Anda untuk melemparkan int ke enum.
Lii

2
Dalam contoh Anda, Anda bisa melempar pengecualian alih-alih kembali setelah pernyataan switch. Dengan cara itu Anda bisa memiliki kedua pemeriksaan statis oleh kompiler dan mendapatkan kesalahan yang jelas jika sesuatu yang tidak terduga terjadi.
Lii

1
Saya setuju. Dalam Swift per contoh, sakelar harus lengkap jika tidak Anda mendapatkan kesalahan kompiler! Menyediakan standar hanya membungkam kesalahan bermanfaat ini. Di sisi lain, memberikan default jika semua kasus ditangani benar-benar melempar peringatan kompiler (pernyataan tidak terjangkau).
Andy

1
Baru saja memperbaiki bug, itu akan menyebabkan peringatan dari Compiler jika tidak ada default: jadi umumnya Variabel Switch over enum seharusnya tidak memiliki default.
notan

42

Saya akan selalu menggunakan klausa default, tidak peduli bahasa apa yang Anda gunakan.

Hal-hal dapat dan memang salah. Nilai tidak akan seperti yang Anda harapkan, dan seterusnya.

Tidak ingin memasukkan klausa default menyiratkan Anda yakin bahwa Anda tahu set nilai yang mungkin. Jika Anda yakin mengetahui set nilai yang mungkin, jika nilai berada di luar nilai yang mungkin, Anda ingin diberi tahu tentangnya - ini tentu saja merupakan kesalahan.

Itulah alasan mengapa Anda harus selalu menggunakan klausa default dan melemparkan kesalahan, misalnya di Jawa:

switch (myVar) {
   case 1: ......; break;
   case 2: ......; break;
   default: throw new RuntimeException("unreachable");
}

Tidak ada alasan untuk memasukkan lebih banyak informasi daripada hanya string yang "tidak terjangkau"; jika itu benar-benar terjadi, Anda harus melihat sumber dan nilai-nilai variabel dll, dan stacktrace pengecualian akan menyertakan nomor baris itu, jadi tidak perlu membuang waktu Anda menulis lebih banyak teks ke dalam pesan pengecualian.


39
Saya lebih suka throw new RuntimeException("myVar invalid " + myVar);karena itu mungkin memberi Anda cukup info untuk mencari tahu dan memperbaiki bug tanpa harus menggunakan debugger dan memeriksa variabel, yang mungkin sulit jika ini adalah masalah yang jarang terjadi yang sulit untuk mereproduksi.
Chris Dodd

1
Bagaimana jika itu bukan kondisi kesalahan untuk nilai yang tidak cocok dengan salah satu kasus?
Gabe

4
Jika ini bukan kondisi kesalahan, maka tidak perlu untuk default:. Tetapi lebih sering tidak, seseorang meninggalkan default karena orang berpikir myVartidak akan pernah memiliki nilai selain dari yang terdaftar; namun saya tidak dapat menghitung berapa kali saya terkejut dalam kehidupan nyata ketika variabel memiliki nilai selain dari nilai-nilai yang "mungkin" miliki. Dalam kasus tersebut, saya berterima kasih atas pengecualian yang membuat saya langsung melihatnya, daripada menyebabkan beberapa kesalahan lain di kemudian hari (lebih sulit untuk di-debug) atau jawaban yang salah (mungkin terlewatkan dalam pengujian).
Adrian Smith

2
Saya setuju dengan Adrian. Gagal dan gagal lebih awal.
Slappy

Saya lebih suka melempar AssertionErrorbukan RuntimeException, karena situasi ini sangat mirip dengan pernyataan yang menyatakan bahwa itu myVaradalah salah satu nilai yang ditangani. Juga kemungkinan seseorang menangkap dan menelan kesalahan lebih kecil.
Philipp Wendler

15

Di perusahaan saya, kami menulis perangkat lunak untuk pasar Avionik dan Pertahanan, dan kami selalu menyertakan pernyataan default, karena SEMUA kasus dalam pernyataan switch harus ditangani secara eksplisit (bahkan jika itu hanya komentar yang mengatakan 'Jangan lakukan apa-apa'). Kami tidak dapat membeli perangkat lunak hanya untuk berperilaku tidak pantas atau hanya mogok pada nilai yang tidak terduga (atau bahkan yang kami pikir tidak mungkin).

Dapat didiskusikan bahwa kasing standar tidak selalu diperlukan, tetapi dengan selalu memerlukannya, kasing mudah diperiksa oleh penganalisa kode kami.


1
Saya memiliki persyaratan yang sama di tempat saya bekerja; kami menulis kode untuk μControllers tertanam yang harus melewati pemeriksaan keamanan yang ketat dan sering dikenakan EMI. Tidak bertanggung jawab untuk mengasumsikan bahwa variabel enumerasi tidak akan pernah memiliki nilai yang tidak ada dalam daftar enumerasi.
oosterwal

12

Haruskah pernyataan "switch" selalu menyertakan klausa default? Tidak Perlu biasanya menyertakan default.

Termasuk klausa default hanya masuk akal jika ada sesuatu untuk dilakukan, seperti menyatakan kondisi kesalahan atau memberikan perilaku default. Termasuk satu "hanya karena" adalah pemrograman pemujaan kargo dan tidak memberikan nilai. Ini adalah "saklar" yang setara dengan mengatakan bahwa semua pernyataan "jika" harus menyertakan "lain".

Berikut ini adalah contoh sepele di mana itu tidak masuk akal:

void PrintSign(int i)
{
    switch (Math.Sign(i))
    {
    case 1:
        Console.Write("positive ");
        break;
    case -1:
        Console.Write("negative ");
        break;
    default: // useless
    }
    Console.Write("integer");
}

Ini setara dengan:

void PrintSign(int i)
{
    int sgn = Math.Sign(i);
    if (sgn == 1)
        Console.Write("positive ");
    else if (sgn == -1)
        Console.Write("negative ");
    else // also useless
    {
    }
    Console.Write("integer");
}

Saya tidak setuju. IMHO, satu-satunya waktu default seharusnya tidak ada adalah jika tidak ada cara, untuk sekarang dan selamanya, bahwa set input dapat berubah, dan Anda memiliki semua nilai yang mungkin tercakup. Kasus paling sederhana yang bisa saya pikirkan adalah nilai boolean dari database, di mana satu-satunya jawaban (sampai SQL berubah!) Adalah benar, salah, dan NULL. Dalam kasus lain, memiliki standar dengan pernyataan atau pengecualian "Tidak Harus Terjadi!" masuk akal. Jika kode Anda berubah, dan Anda memiliki satu atau lebih nilai baru, maka Anda dapat memastikan kode untuk mereka, dan tes Anda akan meledak jika tidak.
Harper Shelby

4
@ Harper: Contoh Anda berada di bawah kategori "menegaskan kondisi kesalahan".
Gabe

Saya akan menegaskan bahwa contoh saya adalah norma, dan bahwa sejumlah kecil kasus di mana seseorang dapat 100% yakin setiap kasus yang mungkin dicakup dan default tidak diperlukan adalah pengecualian. Jawaban Anda diucapkan dengan cara yang membuatnya terdengar (setidaknya bagi saya) seolah-olah default tidak melakukan apa-apa akan terjadi lebih sering daripada tidak.
Harper Shelby

@ Harper: OK, saya mengubah kata-kata untuk menunjukkan bahwa situasi tidak melakukan apa-apa kurang umum.
Gabe

4
Saya pikir default:dalam kasus-kasus itu dikodifikasikan asumsi Anda. Sebagai contoh, apakah boleh ketika sgn==0mencetak integer(baik positif maupun negatif), atau apakah itu kesalahan? Bagi saya membaca kode itu, sulit dikatakan. Saya berasumsi Anda tidak ingin menulis zerodalam kasus itu integer, dan programmer membuat asumsi yang sgnhanya bisa -1 atau +1. Jika itu yang terjadi, memiliki default:akan memungkinkan programmer untuk menangkap asumsi awal dan mengubah kode.
Adrian Smith

7

Sejauh yang saya lihat jawabannya adalah 'default' adalah opsional, mengatakan switch harus selalu berisi default seperti mengatakan setiap 'if-elseif' harus mengandung 'lain'. Jika ada logika yang harus dilakukan secara default, maka pernyataan 'default' harus ada di sana, tetapi sebaliknya kode dapat terus dieksekusi tanpa melakukan apa pun.


6

Memiliki klausa default ketika itu tidak benar - benar diperlukan adalah pemrograman Defensive Ini biasanya mengarah ke kode yang terlalu kompleks karena terlalu banyak kode penanganan kesalahan. Kode penanganan dan deteksi kesalahan ini merusak keterbacaan kode, membuat pemeliharaan lebih sulit, dan akhirnya menyebabkan lebih banyak bug daripada memecahkannya.

Jadi saya percaya bahwa jika defaultnya tidak tercapai - Anda tidak perlu menambahkannya.

Perhatikan bahwa "tidak boleh dijangkau" berarti bahwa jika itu mencapai itu adalah bug dalam perangkat lunak - Anda perlu menguji nilai yang mungkin mengandung nilai yang tidak diinginkan karena input pengguna, dll.


3
Alasan umum lain untuk mendapatkan kasus yang tidak terduga: Bagian lain dari kode dimodifikasi, mungkin bertahun-tahun kemudian.
Hendrik Brummermann

Memang, ini perilaku yang sangat dangourous. Setidaknya, saya akan menambahkan klausa assert (). Maka mudah dideteksi setiap kali ada bug.
Kurt Pattyn

5

Saya akan mengatakan itu tergantung pada bahasa, tetapi dalam C jika Anda mengaktifkan jenis enum dan Anda menangani setiap nilai yang mungkin, Anda mungkin lebih baik TIDAK termasuk case default. Dengan begitu, jika Anda menambahkan tag enum tambahan nanti dan lupa menambahkannya ke sakelar, kompiler yang kompeten akan memberi Anda peringatan tentang kasing yang hilang.


5
"Setiap nilai yang memungkinkan" tidak mungkin ditangani dengan enum. Anda bisa melemparkan integer ke enum bahkan jika nilai tertentu tidak didefinisikan secara eksplisit. Dan kompiler mana yang memperingatkan tentang case yang hilang?
TrueWill

1
@ TrueWill: Ya, Anda dapat menggunakan gips eksplisit untuk menulis kode yang dikaburkan yang tidak mungkin dipahami; untuk menulis kode yang dapat dimengerti, Anda harus menghindari itu. gcc -Wall(semacam penyebut umum yang paling rendah dari kompiler yang kompeten) memberikan peringatan tentang enum yang tidak ditangani dalam pernyataan sakelar.
Chris Dodd

4

Jika Anda tahu bahwa pernyataan switch hanya akan memiliki satu set label atau nilai yang didefinisikan dengan ketat, lakukan saja ini untuk menutupi basis, dengan cara itu Anda akan selalu mendapatkan hasil yang valid .. Masukkan saja default di atas label yang akan diprogram / secara logis menjadi penangan terbaik untuk nilai-nilai lainnya.

switch(ResponseValue)
{
    default:
    case No:
        return false;
    case Yes;
        return true;
}

Apakah usus besar setelah defaultmasih diperlukan di sini? Atau apakah melakukan ini memungkinkan beberapa sintaks khusus yang memungkinkan Anda menghilangkannya?
Ponkadoodle

Usus besar diperlukan, itu salah ketik, terima kasih telah membawanya ke perhatian saya.
deegee

3

Paling tidak itu tidak wajib di Jawa. Menurut JLS, katanya paling tidak satu kasus default dapat hadir. Yang berarti tidak ada case standar yang dapat diterima. Kadang-kadang juga tergantung pada konteks bahwa Anda menggunakan pernyataan switch. Misalnya di Jawa, blok sakelar berikut ini tidak memerlukan kasing standar

private static void switch1(String name) {
    switch (name) {
    case "Monday":
        System.out.println("Monday");
        break;
    case "Tuesday":
        System.out.println("Tuesday");
        break;
    }
}

Tetapi dalam metode berikut yang mengharapkan untuk mengembalikan sebuah String, case default berguna untuk menghindari kesalahan kompilasi

    private static String switch2(String name) {
    switch (name) {
    case "Monday":
        System.out.println("Monday");
        return name;

    case "Tuesday":
        System.out.println("Tuesday");
        return name;

    default:
        return name;
    }
}

meskipun Anda dapat menghindari kesalahan kompilasi untuk metode di atas tanpa memiliki case default dengan hanya memiliki pernyataan pengembalian di akhir, tetapi menyediakan case default membuatnya lebih mudah dibaca.


3

Beberapa pedoman (kedaluwarsa) mengatakan demikian, seperti MISRA C :

Persyaratan untuk klausa default akhir adalah pemrograman defensif. Klausul ini harus mengambil tindakan yang sesuai atau berisi komentar yang sesuai tentang mengapa tidak ada tindakan yang diambil.

Saran itu sudah usang karena tidak didasarkan pada kriteria yang relevan saat ini. Kelalaian yang mencolok adalah apa yang Harlan Kassler katakan:

Meninggalkan case default memungkinkan kompiler untuk secara opsional memperingatkan atau gagal ketika melihat case yang tidak ditangani. Bagaimanapun, verifikasi statis lebih baik daripada pemeriksaan dinamis, dan karenanya bukan pengorbanan yang layak ketika Anda membutuhkan pemeriksaan dinamis juga.

Seperti yang diperlihatkan Harlan, ekuivalen fungsional dari kasing standar dapat diciptakan kembali setelah sakelar. Yang sepele ketika setiap kasus adalah pengembalian awal.

Kebutuhan khas untuk pemeriksaan dinamis adalah penanganan input, dalam arti luas. Jika nilai berasal dari luar kendali program, itu tidak bisa dipercaya.

Di sinilah Misra mengambil sudut pandang pemrograman defensif ekstrem, di mana selama nilai yang tidak valid dapat diwakili secara fisik, itu harus diperiksa, tidak peduli apakah program tersebut terbukti benar. Yang masuk akal jika perangkat lunak harus seandal mungkin dengan adanya kesalahan perangkat keras. Tapi seperti kata Ophir Yoktan, sebagian besar perangkat lunak lebih baik tidak "menangani" bug. Praktek yang terakhir ini kadang-kadang disebut pemrograman ofensif .


2

Anda harus memiliki default untuk menangkap nilai yang tidak diharapkan masuk.

Namun, saya tidak setuju dengan Adrian Smith bahwa pesan kesalahan Anda untuk default seharusnya menjadi sesuatu yang sama sekali tidak berarti. Mungkin ada kasus yang tidak ditangani yang tidak Anda lihat (yang merupakan pokok permasalahan) yang pada akhirnya akan dilihat oleh pengguna Anda dan pesan seperti "tidak dapat dijangkau" sama sekali tidak ada gunanya dan tidak membantu siapa pun dalam situasi itu.

Contohnya, berapa kali Anda mengalami BSOD yang sama sekali tidak berarti? Atau pengecualian fatal @ 0x352FBB3C32342?


misalnya - ingat bukan hanya pengembang yang selalu melihat pesan kesalahan. Kita hidup di dunia nyata, orang membuat kesalahan.
John Hunt

2

Jika nilai sakelar ( sakelar (variabel )) tidak dapat mencapai kasing standar, maka kasing standar sama sekali tidak diperlukan. Bahkan jika kita menyimpan case default, itu sama sekali tidak dieksekusi. Itu kode mati.


2

Ini adalah 'konvensi' pengkodean opsional. Tergantung pada penggunaannya apakah diperlukan atau tidak. Saya pribadi percaya bahwa jika Anda tidak membutuhkannya tidak seharusnya ada di sana. Mengapa menyertakan sesuatu yang tidak akan digunakan atau dijangkau oleh pengguna?

Jika kemungkinan case terbatas (yaitu Boolean) maka klausa default adalah redundan !


2

Jika tidak ada kasus default dalam switchpernyataan, perilaku bisa tidak dapat diprediksi jika kasus itu muncul di beberapa titik waktu, yang tidak dapat diprediksi pada tahap pengembangan. Ini adalah praktik yang baik untuk memasukkan defaultkasus.

switch ( x ){
  case 0 : { - - - -}
  case 1 : { - - - -}
}

/* What happens if case 2 arises and there is a pointer
* initialization to be made in the cases . In such a case ,
* we can end up with a NULL dereference */

Praktek semacam itu dapat menghasilkan bug seperti dereference NULL , kebocoran memori serta jenis bug serius lainnya .

Sebagai contoh, kami berasumsi bahwa setiap kondisi menginisialisasi pointer. Tetapi jika defaultcase seharusnya muncul dan jika kita tidak menginisialisasi dalam kasus ini, maka ada setiap kemungkinan mendarat dengan pengecualian null pointer. Oleh karena itu disarankan untuk menggunakan defaultpernyataan kasus, meskipun itu mungkin sepele.


2

Kasing standar mungkin tidak diperlukan dalam sakelar yang digunakan oleh enum. ketika switch berisi semua nilai, case default tidak akan pernah dijalankan. Jadi dalam hal ini, itu tidak perlu.


1

Bergantung pada bagaimana switch dalam bahasa tertentu bekerja, namun dalam kebanyakan bahasa ketika tidak ada kasus yang cocok, eksekusi jatuh melalui pernyataan switch tanpa peringatan. Bayangkan Anda mengharapkan beberapa set nilai dan menanganinya secara bergantian, namun Anda mendapatkan nilai lain dalam input. Tidak ada yang terjadi dan Anda tidak tahu tidak ada yang terjadi. Jika Anda menangkap case secara default, Anda akan tahu ada sesuatu yang salah.


1

Saya tidak setuju dengan jawaban Vanwaril yang paling banyak dipilih di atas.

Kode apa pun menambah kompleksitas. Juga tes dan dokumentasi harus dilakukan untuk itu. Jadi selalu baik jika Anda dapat memprogram menggunakan lebih sedikit kode. Pendapat saya adalah bahwa saya menggunakan klausa default untuk pernyataan switch tidak lengkap sementara saya tidak menggunakan klausa default untuk pernyataan switch lengkap. Untuk memastikan bahwa saya melakukannya dengan benar, saya menggunakan alat analisis kode statis. Jadi mari kita masuk ke detail:

  1. Tidak ada pernyataan beralih yang lengkap: Itu harus selalu memiliki nilai default. Seperti namanya itu adalah pernyataan yang tidak mencakup semua nilai yang mungkin. Ini juga mungkin tidak mungkin, misalnya pernyataan switch pada nilai integer atau pada String. Di sini saya ingin menggunakan contoh Vanwaril (Harus disebutkan bahwa saya pikir dia menggunakan contoh ini untuk membuat saran yang salah. Saya menggunakannya di sini untuk menyatakan sebaliknya -> Gunakan pernyataan default):

    switch(keystroke)
    {
      case 'w':
        // move up
      case 'a':
        // move left
      case 's':
        // move down
      case 'd':
        // move right
      default:          
        // cover all other values of the non-exhaustive switch statement
    }
    

    Pemain dapat menekan tombol lainnya. Maka kita tidak bisa melakukan apa-apa (ini dapat ditunjukkan dalam kode hanya dengan menambahkan komentar ke case default) atau seharusnya misalnya mencetak sesuatu di layar. Kasus ini relevan karena mungkin terjadi.

  2. Pernyataan sakelar yang lengkap: Pernyataan sakelar tersebut mencakup semua nilai yang mungkin, misalnya, pernyataan sakelar pada enumerasi tipe sistem kelas. Saat mengembangkan kode pertama kali mudah untuk mencakup semua nilai. Namun, karena kita adalah manusia, ada sedikit peluang untuk melupakan sebagian. Selain itu jika Anda menambahkan nilai enum nanti sehingga semua pernyataan beralih harus disesuaikan untuk membuatnya lengkap lagi membuka jalan ke kesalahan neraka. Solusi sederhana adalah alat analisis kode statis. Alat ini harus memeriksa semua pernyataan sakelar dan memeriksa apakah mereka lengkap atau apakah mereka memiliki nilai default. Berikut ini contoh pernyataan peralihan lengkap. Pertama kita membutuhkan enum:

    public enum GradeSystemType {System1To6, SystemAToD, System0To100}
    

    Maka kita perlu variabel seperti enum ini GradeSystemType type = .... Pernyataan sakelar yang lengkap akan terlihat seperti ini:

    switch(type)
    {
      case GradeSystemType.System1To6:
        // do something
      case GradeSystemType.SystemAToD:
        // do something
      case GradeSystemType.System0To100:
        // do something
    }
    

    Jadi, jika kita memperpanjang GradeSystemTypedengan misalnya System1To3alat analisis kode statis harus mendeteksi bahwa tidak ada klausa default dan pernyataan beralih tidak lengkap sehingga kami menyimpan.

Hanya satu hal tambahan. Jika kita selalu menggunakan defaultklausa, mungkin terjadi bahwa alat analisis kode statis tidak mampu mendeteksi pernyataan beralih lengkap atau tidak lengkap karena selalu mendeteksi defaultklausa. Ini sangat buruk karena kami tidak akan diberi tahu jika kami memperpanjang enum dengan nilai lain dan lupa menambahkannya ke satu pernyataan switch.


0

Haruskah beralih pernyataan selalu mengandung klausa default? Tidak ada kasus sakelar yang ada tanpa kasing standar, dalam kasing standar kasing akan memicu nilai sakelar switch(x)dalam kasing x ini ketika tidak cocok dengan nilai kasing lainnya.


0

Saya percaya ini cukup spesifik bahasa dan untuk kasus C ++ titik kecil untuk tipe kelas enum . Yang tampak lebih aman daripada C enum tradisional. TAPI

Jika Anda melihat implementasi std :: byte-nya sesuatu seperti:

enum class byte : unsigned char {} ;

Sumber: https://en.cppreference.com/w/cpp/language/enum

Dan pertimbangkan juga ini:

Sebaliknya, jika T adalah tipe enumerasi yang scoped atau unscoped dengan tipe dasar tetap, dan jika bracing-init-list hanya memiliki satu inisialisasi, dan jika konversi dari inisialisasi ke tipe yang mendasarinya tidak menyempit, dan jika inisialisasi adalah daftar-inisialisasi langsung, kemudian enumerasi diinisialisasi dengan hasil mengubah inisialisasi ke tipe yang mendasarinya.

(sejak C ++ 17)

Sumber: https://en.cppreference.com/w/cpp/language/list_initialization

Ini adalah contoh kelas enum yang mewakili nilai-nilai yang tidak didefinisikan enumerator. Karena alasan ini, Anda tidak dapat menaruh kepercayaan penuh pada enum. Tergantung pada aplikasi ini mungkin penting.

Namun, saya sangat suka apa yang dikatakan @Harlan Kassler di posnya dan akan mulai menggunakan strategi itu dalam beberapa situasi sendiri.

Contoh kelas enum yang tidak aman:

enum class Numbers : unsigned
{
    One = 1u,
    Two = 2u
};

int main()
{
    Numbers zero{ 0u };
    return 0;
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.