Apa manfaat / kerugian menggunakan switch
pernyataan vs. if/else
dalam C #. Saya tidak bisa membayangkan ada perbedaan besar, selain mungkin tampilan kode Anda.
Apakah ada alasan mengapa IL yang dihasilkan atau kinerja runtime terkait akan sangat berbeda?
Terkait: Apa yang lebih cepat, aktifkan string atau kalau tidak ketik?
c#
.net
switch-statement
Matius M. Osborn
sumber
sumber
Jawaban:
Pernyataan SWITCH hanya menghasilkan perakitan yang sama dengan IF dalam mode debug atau kompatibilitas. Dalam rilis, itu akan dikompilasi ke dalam tabel lompatan (melalui pernyataan 'saklar' MSIL) - yaitu O (1).
C # (tidak seperti banyak bahasa lain) juga memungkinkan untuk mengaktifkan konstanta string - dan ini bekerja sedikit berbeda. Jelas tidak praktis untuk membuat tabel lompatan untuk string yang panjangnya sewenang-wenang, jadi paling sering saklar semacam itu akan dikompilasi ke dalam tumpukan IF.
Tetapi jika jumlah kondisi cukup besar untuk menutupi overhead, kompiler C # akan membuat objek HashTable, isi dengan konstanta string dan buat pencarian di atas meja itu diikuti dengan lompatan. Pencarian Hashtable tidak sepenuhnya O (1) dan memiliki biaya konstan yang nyata, tetapi jika jumlah label kasus besar, itu akan secara signifikan lebih cepat daripada membandingkan dengan setiap string konstan dalam IF.
Singkatnya, jika jumlah kondisi lebih dari 5 atau lebih, pilih SWITCH daripada IF, jika tidak gunakan apa pun yang terlihat lebih baik.
sumber
Secara umum (mempertimbangkan semua bahasa dan semua kompiler) pernyataan switch DAPAT SESUATU lebih efisien daripada pernyataan if / else, karena mudah bagi kompiler untuk menghasilkan tabel lompatan dari pernyataan switch. Dimungkinkan untuk melakukan hal yang sama untuk pernyataan if / else, dengan batasan yang sesuai, tetapi itu jauh lebih sulit.
Dalam kasus C #, ini juga benar, tetapi karena alasan lain.
Dengan sejumlah besar string, ada keuntungan kinerja yang signifikan untuk menggunakan pernyataan switch, karena kompiler akan menggunakan tabel hash untuk mengimplementasikan lompatan.
Dengan sejumlah kecil string, kinerja keduanya sama.
Ini karena dalam kasus itu kompiler C # tidak menghasilkan tabel lompatan. Alih-alih itu menghasilkan MSIL yang setara dengan blok IF / ELSE.
Ada instruksi MSIL "switch statement" yang ketika dipasangkan akan menggunakan tabel lompat untuk mengimplementasikan pernyataan switch. Namun, ini hanya bekerja dengan tipe integer (pertanyaan ini menanyakan tentang string).
Untuk sejumlah kecil string, ini lebih efisien bagi kompiler untuk menghasilkan blok IF / ELSE daripada menggunakan tabel hash.
Ketika saya awalnya memperhatikan hal ini, saya membuat asumsi bahwa karena blok IF / ELSE digunakan dengan sejumlah kecil string, maka kompiler melakukan transformasi yang sama untuk sejumlah besar string.
Ini SALAH. 'IMA' cukup baik untuk menunjukkan hal ini kepada saya (well ... dia tidak baik tentang itu, tapi dia benar, dan saya salah, yang merupakan bagian penting)
Saya juga membuat asumsi berkepala tentang kurangnya "saklar" instruksi di MSIL (saya pikir, jika ada saklar primitif, mengapa mereka tidak menggunakannya dengan tabel hash, jadi tidak boleh ada saklar primitif. ...). Ini salah, dan sangat bodoh di pihak saya. Sekali lagi 'IMA' menunjukkan ini kepada saya.
Saya membuat pembaruan di sini karena itu adalah posting berperingkat tertinggi, dan jawaban yang diterima.
Namun, saya telah membuatnya menjadi Komunitas Wiki karena saya pikir saya tidak pantas menerima REP karena salah. Jika Anda mendapat kesempatan, silakan pilih posting 'ima'.
sumber
Tiga alasan untuk memilih
switch
:Sebuah kompiler yang menargetkan kode asli sering dapat mengkompilasi pernyataan switch ke satu cabang kondisional ditambah lompatan tidak langsung sedangkan urutan
if
s membutuhkan urutan cabang kondisional . Tergantung pada kepadatan kasus, banyak makalah yang dipelajari telah ditulis tentang bagaimana menyusun laporan kasus secara efisien; beberapa ditautkan dari halaman kompiler lcc . (Lcc memiliki salah satu kompiler yang lebih inovatif untuk sakelar.)Pernyataan switch adalah pilihan di antara alternatif yang saling eksklusif dan sintaksis saklar membuat aliran kontrol ini lebih transparan kepada programmer daripada sarang pernyataan if-then-else.
Dalam beberapa bahasa, termasuk pasti ML dan Haskell, kompiler akan memeriksa untuk melihat apakah Anda telah meninggalkan kasus apa pun . Saya melihat fitur ini sebagai salah satu keunggulan utama ML dan Haskell. Saya tidak tahu apakah C # dapat melakukan ini.
Sebuah anekdot: pada sebuah kuliah yang dia berikan ketika menerima penghargaan untuk pencapaian seumur hidup, saya mendengar Tony Hoare mengatakan bahwa dari semua hal yang dia lakukan dalam karirnya, ada tiga yang paling dia banggakan:
case
statement)Saya tidak bisa membayangkan hidup tanpa
switch
.sumber
Kompiler akan mengoptimalkan hampir semuanya menjadi kode yang sama dengan perbedaan kecil (Knuth, ada orang?).
Perbedaannya adalah bahwa pernyataan switch lebih bersih dari lima belas jika pernyataan lain dirangkai.
Teman tidak membiarkan teman menumpuk pernyataan if-else.
sumber
Sebenarnya, pernyataan switch lebih efisien. Kompiler akan mengoptimalkannya ke tabel mencari di mana dengan pernyataan if / else tidak bisa. Sisi bawahnya adalah bahwa pernyataan switch tidak dapat digunakan dengan nilai variabel.
Anda tidak dapat melakukan:
itu harus
sumber
Saya tidak melihat orang lain meningkatkan (jelas?) Titik bahwa keuntungan efisiensi seharusnya dari pernyataan switch tergantung pada berbagai kasus yang kira-kira sama-sama mungkin. Dalam kasus-kasus di mana satu (atau beberapa) dari nilai-nilai itu jauh lebih mungkin, tangga jika-maka-yang lain bisa lebih cepat, dengan memastikan kasus-kasus yang paling umum diperiksa terlebih dahulu:
Jadi, misalnya:
vs.
Jika x adalah nol 90% dari waktu, kode "jika lain" bisa dua kali lebih cepat dari kode berbasis switch. Bahkan jika kompiler mengubah "switch" menjadi semacam goto pintar yang digerakkan oleh tabel, itu masih tidak akan secepat hanya dengan memeriksa nol.
sumber
switch
kompatibel,switch
pernyataannya lebih baik (lebih mudah dibaca, terkadang lebih cepat). Jika Anda tahu bahwa satu kasing jauh lebih mungkin, Anda dapat menariknya keluar untuk membentukif
-else
-switch
konstruk dan jika lebih cepat terukur , Anda membiarkannya masuk (Ulangi, jika perlu.) IMO yang masih dapat dibaca. Jikaswitch
degenerasi dan menjadi terlalu kecil, regex-replace akan melakukan sebagian besar pekerjaan mengubahnya menjadi-else if
rantai.seringkali akan terlihat lebih baik - yaitu akan lebih mudah untuk memahami apa yang terjadi. Mengingat manfaat kinerja akan sangat minimal, pandangan kode adalah perbedaan yang paling penting.
Jadi, jika if / else terlihat lebih baik, gunakan itu, kalau tidak gunakan pernyataan switch.
sumber
Topik sampingan, tetapi saya sering khawatir tentang (dan lebih sering melihat)
if
/else
danswitch
pernyataan terlalu besar dengan terlalu banyak kasus. Ini sering melukai rawatan.Penyebab umum meliputi:
Memperbaiki:
sumber
Sesuai tautan ini, perbandingan IF vs Switch dari tes iterasi menggunakan switch dan if statement, seperti untuk 1.000.000.000 iterasi, Waktu yang diambil oleh Switch Statement = 43.0s & oleh If Statement = 48.0s
Yang secara harfiah adalah 20833333 iterasi per detik, Jadi, Jika kita benar-benar perlu lebih fokus,
PS: Hanya untuk mengetahui perbedaan kinerja untuk daftar kecil kondisi.
sumber
Jika Anda hanya menggunakan pernyataan if atau lainnya, solusi dasar menggunakan perbandingan? operator
Anda dapat melakukan atau rutin dalam suatu saklar
sumber
Ini sebenarnya tidak menjawab pertanyaan Anda, tetapi mengingat akan ada sedikit perbedaan antara versi yang dikompilasi, saya akan mendorong Anda untuk menulis kode Anda dengan cara yang paling menggambarkan niat Anda. Tidak hanya ada peluang yang lebih baik dari kompiler melakukan apa yang Anda harapkan, tetapi juga akan memudahkan orang lain untuk menjaga kode Anda.
Jika niat Anda adalah untuk bercabang program Anda berdasarkan nilai satu variabel / atribut, maka pernyataan switch paling mewakili niat itu.
Jika niat Anda adalah bercabang program Anda berdasarkan variabel / atribut / kondisi yang berbeda, maka rantai if / else jika rantai terbaik mewakili niat itu.
Saya akan mengabulkan bahwa cody benar tentang orang yang melupakan perintah break, tetapi hampir sering saya melihat orang melakukan rumit jika blok di mana mereka mendapatkan {} salah, sehingga baris yang seharusnya dalam pernyataan kondisional tidak. Itu salah satu alasan saya selalu memasukkan {} pada pernyataan if saya meskipun ada satu baris di dalamnya. Tidak hanya lebih mudah dibaca, tetapi jika saya perlu menambahkan baris lain dalam kondisional, saya tidak bisa lupa untuk menambahkannya.
sumber
Pertanyaan minat. Ini muncul beberapa minggu yang lalu di tempat kerja dan kami menemukan jawaban dengan menulis cuplikan contoh dan melihatnya di. NET Reflector (reflektornya luar biasa !! Saya menyukainya).
Inilah yang kami temukan: Pernyataan switch yang valid untuk apa pun selain string akan dikompilasi ke IL sebagai pernyataan switch. Namun JIKA itu adalah string itu ditulis ulang sebagai if / else if / else di IL. Jadi dalam kasus kami, kami ingin tahu bagaimana pernyataan peralihan membandingkan string, misalnya, peka terhadap huruf, dll. Dan reflektor dengan cepat memberi kami jawaban. Ini berguna untuk diketahui.
Jika Anda ingin melakukan perbandingan case-sensitif pada string maka Anda bisa menggunakan pernyataan switch karena lebih cepat daripada melakukan String. Bandingkan dalam if / else. (Sunting: Baca Apa yang lebih cepat, aktifkan string atau jika tidak ketik? Untuk beberapa tes kinerja aktual) Namun jika Anda ingin melakukan case-insensitive maka lebih baik menggunakan if / else karena kode yang dihasilkan tidak cantik.
Aturan praktis terbaik adalah dengan menggunakan pernyataan switch jika masuk akal (serius), misalnya:
Jika Anda perlu memanipulasi nilai untuk dimasukkan ke dalam pernyataan switch (buat variabel sementara untuk beralih melawan) maka Anda mungkin harus menggunakan pernyataan kontrol if / else.
Sebuah pembaharuan:
Sebenarnya lebih baik untuk mengonversi string menjadi huruf besar (misalnya
ToUpper()
) karena yang telah ada ternyata ada optimasi lebih lanjut bahwa kompiler just-in-time dapat melakukan seperti ketika dibandingkan denganToLower()
. Ini adalah optimasi mikro, namun dalam lingkaran yang ketat itu bisa berguna.Catatan kecil:
Untuk meningkatkan keterbacaan pernyataan beralih coba yang berikut ini:
sumber
Pernyataan peralihan jelas lebih cepat dari pada if if if if. Ada speedtest yang disediakan oleh BlackWasp
http://www.blackwasp.co.uk/SpeedTestIfElseSwitch.aspx
--Saksikan berikut ini
Tetapi sangat bergantung pada kemungkinan yang Anda coba pertanggungjawabkan, tetapi saya mencoba menggunakan pernyataan peralihan bila memungkinkan.
sumber
Bukan hanya C #, tetapi semua bahasa berbasis C, saya pikir: karena sebuah saklar terbatas pada konstanta, dimungkinkan untuk menghasilkan kode yang sangat efisien menggunakan "tabel lompatan". Kasing C benar-benar FORTRAN tua yang baik dihitung GOTO, tetapi kasing C # masih menguji terhadap konstan.
Ini bukan masalah bahwa pengoptimal akan dapat membuat kode yang sama. Pertimbangkan, misalnya,
Karena itu adalah boolean majemuk, kode yang dihasilkan harus menghitung nilai, dan sirkuit pendek. Sekarang pertimbangkan yang setara
Ini dapat dikompilasi menjadi
karena Anda secara implisit memberi tahu kompiler bahwa ia tidak perlu menghitung tes OR dan kesetaraan.
sumber
Profesor cs saya menyarankan agar Anda tidak beralih pernyataan karena begitu sering orang lupa istirahat atau menggunakannya dengan salah. Saya tidak dapat mengingat dengan tepat apa yang dia katakan tetapi sesuatu di sepanjang baris yang melihat beberapa basis kode mani yang menunjukkan contoh pernyataan switch (tahun lalu) juga memiliki banyak kesalahan di dalamnya.
sumber
Sesuatu yang saya perhatikan adalah Anda dapat menggabungkan if / else dan beralih pernyataan! Sangat berguna ketika perlu memeriksa prasyarat.
sumber
I Think Switch Lebih Cepat Daripada Jika Syaratnya Suka Melihat Ada Program Seperti:
Tulis Program untuk memasukkan angka (antara 1 - 99) dan periksa di slot mana a) 1 - 9 lalu slot satu b) 11 - 19 lalu slot dua c) 21-29 lalu slot tiga dan seterusnya hingga 89- 99
Kemudian Aktif Jika Anda Harus Membuat Banyak Kondisi Tetapi Son Switch Case, Anda Harus Mengetik Saja
itu akan sangat mudah
Ada Banyak Lagi Contoh Seperti Itu Juga!
sumber
pernyataan switch pada dasarnya adalah perbandingan untuk kesetaraan. acara keyboard memiliki keuntungan besar daripada beralih pernyataan ketika memiliki mudah untuk menulis dan membaca kode maka pernyataan if ifif akan, kehilangan {bracket} bisa mendapatkan masalah juga.
Pernyataan ifif jika bagus untuk lebih dari satu solusi jika (jumlahOfApples lebih besar dari 5&&mountOfApples kurang dari 10) simpan apel Anda lagi jika (jumlahOfApples lebih besar dari 10 || theAmountOfApples menjual apel Anda. Saya tidak menulis c # atau c ++ tapi saya mempelajarinya sebelum saya belajar java dan mereka adalah bahasa yang dekat.
sumber
Salah satu kemungkinan kerugian dari pernyataan switch adalah kurangnya beberapa kondisi. Anda dapat memiliki beberapa kondisi untuk if (else) tetapi tidak banyak statement cases dengan kondisi berbeda dalam switch.
Pernyataan switch tidak cocok untuk operasi logika di luar lingkup persamaan / ekspresi Boolean sederhana. Untuk persamaan / ekspresi Boolean itu, sangat cocok tetapi tidak untuk operasi logika lainnya.
Anda memiliki lebih banyak kebebasan dengan logika yang tersedia di pernyataan If tetapi keterbacaan dapat menderita jika pernyataan If menjadi berat atau ditangani dengan buruk.
Keduanya ada di sana tergantung pada konteks apa yang Anda hadapi.
sumber