Kapan tepat menggunakan statement switch fall-through (klasik)? Apakah penggunaan seperti itu direkomendasikan dan dianjurkan atau haruskah dihindari dengan cara apa pun?
Kapan tepat menggunakan statement switch fall-through (klasik)? Apakah penggunaan seperti itu direkomendasikan dan dianjurkan atau haruskah dihindari dengan cara apa pun?
Jawaban:
Inilah contoh di mana itu akan berguna.
public Collection<LogItems> GetAllLogItems(Level level) {
Collection<LogItems> result = new Collection<LogItems>();
switch (level) {
// Note: fall through here is INTENTIONAL
case All:
case Info:
result.Add(GetItemsForLevel(Info));
case Warning:
result.Add(GetItemsForLevel(Warning));
case Error:
result.Add(GetItemsForLevel(Error));
case Critical:
result.Add(GetItemsForLevel(Critical));
case None:
}
return result;
}
Hal semacam ini (di mana satu kasus termasuk yang lain) agak jarang, saya pikir, itulah sebabnya beberapa bahasa yang lebih baru tidak mengizinkan fallover atau memerlukan sintaks khusus untuk itu.
// INTENTIONAL FALL THROUGH HERE
komentar lengkap yang diperlukan.
GetItemsForLevel(Info)
meminta panggilan GetItemsForLevel(Warning)
dan sebagainya.
Saya menggunakannya ketika fungsi tertentu harus diterapkan untuk lebih dari satu nilai. Misalnya, Anda memiliki objek dengan properti bernama operationCode. Jika kode sama dengan 1, 2, 3 atau 4, Anda ingin memulaiOperationX (). Jika 5 atau 6, Anda ingin memulai operasi () dan 7 Anda memulai operasi (). Mengapa ada 7 case lengkap dengan fungsionalitas dan istirahat ketika Anda dapat menggunakan fall-throughs?
Saya pikir itu sepenuhnya valid dalam situasi tertentu, terutama jika itu menghindari 100 pernyataan if-else. =)
switch
dengan beberapa case
s yang terkait dengan kode yang sama. Itu berbeda dari kegagalan, di mana eksekusi satu case
berlanjut ke yang berikutnya karena kurangnya a di break
antara mereka.
Kasing jatuh baik-baik saja. Saya sering menemukan bahwa enumerasi digunakan di banyak tempat, dan ketika Anda tidak perlu membedakan beberapa kasus, lebih mudah menggunakan logika fall-through.
Misalnya (perhatikan komentar penjelas):
public boolean isAvailable(Server server, HealthStatus health) {
switch(health) {
// Equivalent positive cases
case HEALTHY:
case UNDER_LOAD:
return true;
// Equivalent negative cases
case FAULT_REPORTED:
case UNKNOWN:
case CANNOT_COMMUNICATE:
return false;
// Unknown enumeration!
default:
LOG.warn("Unknown enumeration " + health);
return false;
}
}
Saya menemukan penggunaan semacam ini bisa diterima.
case X: case Y: doSomething()
dan case X: doSomething(); case Y: doAnotherThing()
. Dalam yang pertama, niatnya cukup eksplisit, sedangkan yang kedua, kejatuhannya mungkin disengaja atau tidak. Dalam pengalaman saya, contoh pertama tidak pernah memicu peringatan apa pun di kompiler / penganalisa kode, sedangkan yang kedua tidak. Secara pribadi, saya hanya akan menyebut contoh kedua "gagal" - tidak yakin tentang definisi "resmi".
Tergantung pada:
Dua masalah utama yang terkait dengan membiarkan satu kasus jatuh ke yang berikutnya adalah:
Itu membuat kode Anda tergantung pada urutan pernyataan kasus. Itu tidak terjadi jika Anda tidak pernah gagal, dan itu menambah tingkat kerumitan yang sering tidak diinginkan.
Tidak jelas bahwa kode untuk satu kasus menyertakan kode untuk satu atau lebih kasus berikutnya.
Beberapa tempat secara eksplisit melarang jatuh. Jika Anda tidak bekerja di tempat seperti itu, dan jika Anda merasa nyaman dengan latihan itu, dan jika melanggar kode yang dimaksud tidak akan menyebabkan penderitaan nyata, maka itu mungkin bukan hal terburuk di dunia. Namun, jika Anda melakukannya, pastikan untuk meletakkan komentar yang menarik perhatian di dekat untuk memperingatkan mereka yang datang kemudian (termasuk masa depan Anda).
Berikut adalah contoh cepat (diakui tidak lengkap (tidak ada penanganan khusus tahun kabisat)) yang membuat hidup saya lebih sederhana:
function get_julian_day (date) {
int utc_date = date.getUTCDate();
int utc_month = date.getUTCMonth();
int julian_day = 0;
switch (utc_month) {
case 11: julian_day += 30;
case 10: julian_day += 31;
case 9: julian_day += 30;
case 8: julian_day += 31;
case 7: julian_day += 31;
case 6: julian_day += 30;
case 5: julian_day += 31;
case 4: julian_day += 30;
case 3: julian_day += 31;
case 2: julian_day += 28;
case 1: julian_day += 31;
default: break;
}
return julian_day + utc_date;
}
Jika saya merasa perlu untuk beralih dari satu kasus ke kasus lain (jarang, harus diakui), saya lebih suka untuk menjadi sangat eksplisit dan goto case
, tentu saja, yang mengasumsikan bahasa Anda mendukungnya.
Karena jatuh melalui sangat jarang, dan sangat mudah untuk diabaikan saat membaca kode, saya merasa pantas untuk eksplisit - dan goto, bahkan jika itu untuk sebuah kasus, harus menonjol seperti jempol yang sakit.
Ini juga membantu menghindari bug yang mungkin terjadi ketika pernyataan kasus disusun ulang.