Saat ini saya sedang dalam proses menulis aplikasi Windows Forms pertama saya. Saya telah membaca beberapa buku C # sekarang jadi saya memiliki pemahaman yang relatif baik tentang fitur bahasa apa yang harus ditangani C # dengan pengecualian. Namun semuanya cukup teoritis jadi yang belum saya dapatkan adalah bagaimana menerjemahkan konsep dasar ke dalam model penanganan pengecualian yang baik dalam aplikasi saya.
Adakah yang ingin berbagi mutiara kebijaksanaan tentang hal ini? Posting kesalahan umum yang Anda lihat yang dilakukan oleh pemula seperti saya, dan saran umum tentang menangani pengecualian dengan cara yang akan membuat aplikasi saya lebih stabil dan kuat.
Hal utama yang saat ini saya coba lakukan adalah:
- Kapan saya harus mengembalikan pengecualian?
- Haruskah saya mencoba memiliki mekanisme penanganan kesalahan terpusat?
- Apakah menangani pengecualian yang mungkin terlempar memiliki performa yang lebih baik dibandingkan dengan pengujian secara pre-emptive seperti apakah file pada disk ada?
- Haruskah semua kode yang dapat dieksekusi diapit dalam blok coba-tangkap-akhirnya?
- Adakah saat-saat ketika blok tangkap kosong mungkin dapat diterima?
Semua nasihat diterima dengan rasa syukur!
sumber
ApplicationException
untuk kasus kegagalan tersebut yang seharusnya dapat dibedakan dan ditangani oleh aplikasi.Ada artikel CodeProject kode yang sangat baik di sini . Berikut ini beberapa sorotan:
sumber
Perhatikan bahwa Windows Forms memiliki mekanisme penanganan pengecualiannya sendiri. Jika tombol dalam formulir diklik dan penangannya melontarkan pengecualian yang tidak tertangkap dalam penangan, Formulir Windows akan menampilkan Dialog Pengecualian Tak Tertangani sendiri.
Untuk mencegah Unhandled Exception Dialog ditampilkan dan menangkap pengecualian tersebut untuk logging dan / atau untuk menyediakan dialog error Anda sendiri, Anda dapat melampirkan ke event Application.ThreadException sebelum panggilan ke Application.Run () dalam metode Main () Anda.
sumber
Sejauh ini, semua saran yang diposting di sini bagus dan patut diperhatikan.
Satu hal yang ingin saya perluas adalah pertanyaan Anda "Apakah menangani pengecualian yang mungkin muncul memiliki performa yang lebih baik dibandingkan dengan pengujian sebelumnya seperti apakah ada file di disk?"
Aturan praktis yang naif adalah "blok coba / tangkap itu mahal." Itu tidak benar. Mencoba tidaklah mahal. Penangkapannya, di mana sistem harus membuat objek Exception dan memuatnya dengan pelacakan tumpukan, itu mahal. Ada banyak kasus di mana pengecualiannya, yah, cukup luar biasa sehingga tidak masalah untuk membungkus kode dalam blok coba / tangkap.
Misalnya, jika Anda mengisi Kamus, ini:
sering kali lebih cepat daripada melakukan ini:
untuk setiap item yang Anda tambahkan, karena pengecualian hanya dilemparkan saat Anda menambahkan kunci duplikat. (Kueri agregat LINQ melakukan ini.)
Dalam contoh yang Anda berikan, saya akan menggunakan coba / tangkap hampir tanpa berpikir. Pertama, hanya karena file tersebut ada saat Anda memeriksanya, bukan berarti file itu akan ada saat Anda membukanya, jadi Anda harus benar-benar menangani pengecualian tersebut.
Kedua, dan saya pikir yang lebih penting, kecuali a) proses Anda membuka ribuan file dan b) kemungkinan file yang coba dibuka tidak ada tidak terlalu rendah, kinerja hit untuk membuat pengecualian bukanlah sesuatu yang Anda ' akan memperhatikan. Secara umum, ketika program Anda mencoba membuka file, program itu hanya mencoba membuka satu file. Itu adalah kasus di mana menulis kode yang lebih aman hampir pasti akan lebih baik daripada menulis kode secepat mungkin.
sumber
dict[key] = value
yang seharusnya secepat jika tidak lebih cepat ..Berikut beberapa pedoman yang saya ikuti
Fail-Fast: Ini lebih merupakan panduan pembuatan pengecualian, Untuk setiap asumsi yang Anda buat dan setiap parameter yang Anda masukkan ke suatu fungsi lakukan pemeriksaan untuk memastikan bahwa Anda memulai dengan data yang benar dan asumsi Anda Pembuatannya benar. Pemeriksaan khas termasuk, argumen bukan nol, argumen dalam kisaran yang diharapkan, dll.
Saat melempar ulang, pertahankan pelacakan tumpukan - Ini berarti menggunakan lemparan saat melempar ulang alih-alih melempar Exception () baru. Atau jika Anda merasa bahwa Anda dapat menambahkan lebih banyak informasi, maka bungkus pengecualian asli sebagai pengecualian dalam. Tetapi jika Anda menangkap pengecualian hanya untuk mencatatnya maka pasti gunakan lemparan;
Jangan menangkap pengecualian yang tidak dapat Anda tangani, jadi jangan khawatir tentang hal-hal seperti OutOfMemoryException karena jika terjadi, Anda tidak akan dapat berbuat banyak.
Lakukan hook penangan pengecualian global dan pastikan untuk mencatat informasi sebanyak mungkin. Untuk winforms, kaitkan appdomain dan thread peristiwa pengecualian yang tidak tertangani.
Performa sebaiknya hanya dipertimbangkan saat Anda menganalisis kode dan melihat bahwa hal itu menyebabkan kemacetan performa, secara default mengoptimalkan keterbacaan dan desain. Jadi tentang pertanyaan asli Anda pada pemeriksaan keberadaan file, saya akan mengatakan itu tergantung, Jika Anda dapat melakukan sesuatu tentang file yang tidak ada di sana, maka ya lakukan itu, periksa sebaliknya jika semua yang akan Anda lakukan adalah melempar pengecualian jika file itu tidak ada maka saya tidak mengerti intinya.
Pasti ada saat-saat ketika blok tangkapan kosong diperlukan, saya pikir orang yang mengatakan sebaliknya tidak bekerja pada basis kode yang telah berevolusi selama beberapa rilis. Tetapi mereka harus diberi komentar dan ditinjau untuk memastikan bahwa mereka benar-benar dibutuhkan. Contoh paling umum adalah pengembang menggunakan try / catch untuk mengonversi string menjadi integer daripada menggunakan ParseInt ().
Jika Anda mengharapkan pemanggil kode Anda untuk dapat menangani kondisi kesalahan, maka buat pengecualian khusus yang merinci situasi yang tidak dapat dikecualikan dan memberikan informasi yang relevan. Jika tidak, cukup gunakan jenis pengecualian bawaan sebanyak mungkin.
sumber
Application.ThreadException
acara saat Anda mereferensikan acara "untaian pengecualian yang tidak ditangani "?Saya suka filosofi tidak menangkap apa pun yang tidak ingin saya tangani, apa pun arti penanganannya dalam konteks khusus saya.
Saya benci jika saya melihat kode seperti:
Saya telah melihat ini dari waktu ke waktu dan cukup sulit untuk menemukan masalah ketika seseorang 'memakan' pengecualian tersebut. Seorang rekan kerja saya melakukan ini dan cenderung berakhir menjadi kontributor arus masalah.
Saya membuang kembali jika ada sesuatu yang kelas khusus saya perlu lakukan sebagai tanggapan atas pengecualian tetapi masalahnya perlu digelembungkan untuk bagaimanapun disebut metode di mana itu terjadi.
Saya pikir kode harus ditulis secara proaktif dan pengecualian harus untuk situasi luar biasa, bukan untuk menghindari pengujian untuk kondisi.
sumber
Saya baru saja keluar tetapi akan memberi Anda penjelasan singkat tentang di mana harus menggunakan penanganan pengecualian. Saya akan mencoba untuk membahas poin Anda yang lain ketika saya kembali :)
*Dengan alasan. Tidak perlu memeriksa untuk melihat apakah sinar kosmik mengenai data Anda menyebabkan beberapa bit terbalik. Memahami apa yang "masuk akal" adalah keterampilan yang diperoleh seorang insinyur. Sulit untuk diukur, namun mudah untuk dipahami. Artinya, saya dapat dengan mudah menjelaskan mengapa saya menggunakan coba / tangkap dalam contoh tertentu, namun saya sulit sekali untuk mengilhami orang lain dengan pengetahuan yang sama ini.
I untuk satu cenderung menjauhi arsitektur berbasis pengecualian. try / catch tidak memiliki hit kinerja seperti itu, klik masuk ketika pengecualian dilemparkan dan kode mungkin harus berjalan naik beberapa tingkat tumpukan panggilan sebelum sesuatu menanganinya.
sumber
Aturan emas yang telah dicoba untuk dipegang adalah menangani pengecualian sedekat mungkin dengan sumbernya.
Jika Anda harus melempar ulang pengecualian, coba tambahkan, melempar kembali FileNotFoundException tidak banyak membantu, tetapi dengan melontarkan ConfigurationFileNotFoundException, hal itu akan memungkinkannya ditangkap dan ditindaklanjuti di suatu tempat di rantai.
Aturan lain yang saya coba ikuti adalah tidak menggunakan try / catch sebagai bentuk alur program, jadi saya memverifikasi file / koneksi, memastikan objek telah dimulai, dll .. sebelum menggunakannya. Coba / tangkap harus untuk Pengecualian, hal-hal yang tidak dapat Anda kendalikan.
Sedangkan untuk blok catch kosong, jika Anda melakukan sesuatu yang penting dalam kode yang menghasilkan pengecualian, Anda harus membuang pengecualian tersebut minimal. Jika tidak ada konsekuensi dari kode yang melemparkan pengecualian tidak berjalan mengapa Anda menulisnya di tempat pertama.
sumber
Anda bisa menjebak acara ThreadException.
Pilih proyek Aplikasi Windows di Solution Explorer.
Buka file Program.cs yang dihasilkan dengan mengklik dua kali di atasnya.
Tambahkan baris kode berikut ke bagian atas file kode:
Dalam metode Main (), tambahkan berikut ini sebagai baris pertama metode:
Tambahkan yang berikut di bawah metode Main ():
Tambahkan kode untuk menangani pengecualian yang tidak tertangani dalam event handler. Pengecualian apa pun yang tidak ditangani di mana pun dalam aplikasi ditangani oleh kode di atas. Paling umum, kode ini harus mencatat kesalahan dan menampilkan pesan kepada pengguna.
refence: https://blogs.msmvps.com/deborahk/global-exception-handler-winforms/
sumber
Pengecualian itu mahal tapi perlu. Anda tidak perlu membungkus semuanya dalam try catch tetapi Anda perlu memastikan bahwa pengecualian selalu tertangkap pada akhirnya. Sebagian besar tergantung pada desain Anda.
Jangan lempar ulang jika membiarkan pengecualian meningkat juga akan berhasil. Jangan biarkan kesalahan berlalu begitu saja.
contoh:
Jika DoStuff mengalami kesalahan, Anda pasti menginginkannya untuk ditebus. Pengecualian akan dilemparkan ke main dan Anda akan melihat rangkaian kejadian di jejak tumpukan ex.
sumber
Di mana-mana, kecuali metode pengguna akhir ... seperti penangan klik tombol
Saya menulis file log ... cukup mudah untuk aplikasi WinForm
Saya tidak yakin tentang ini, tetapi saya yakin ini adalah praktik yang baik untuk memberikan pengecualian ... Maksud saya, Anda dapat bertanya apakah file itu ada dan jika tidak menampilkan FileNotFoundException
yeap
Ya, katakanlah Anda ingin menunjukkan tanggal, tetapi Anda tidak tahu bagaimana tanggal itu disimpan (hh / bb / tttt, bb / hh / tttt, dll) Anda coba tp parse tetapi jika gagal, lanjutkan saja .. Jika tidak relevan bagi Anda ... Saya akan mengatakan ya, ada
sumber
Satu hal yang saya pelajari dengan sangat cepat adalah untuk benar-benar menyertakan setiap potongan kode yang berinteraksi dengan apa pun di luar aliran program saya (yaitu Sistem File, Panggilan Database, Input Pengguna) dengan blok coba-tangkap. Try-catch dapat menyebabkan performa yang buruk, tetapi biasanya di tempat-tempat ini dalam kode Anda hal itu tidak akan terlihat dan akan terbayar dengan sendirinya dengan aman.
Saya telah menggunakan blok-tangkap kosong di tempat-tempat di mana pengguna mungkin melakukan sesuatu yang sebenarnya tidak "salah", tetapi itu dapat membuat pengecualian ... contoh yang terlintas dalam pikiran ada di GridView jika pengguna DoubleCLicks tempat penampung abu-abu sel di kiri atas itu akan mengaktifkan acara CellDoubleClick, tetapi sel tersebut bukan milik sebuah baris. Dalam hal ini, Anda tidak benar-benar perlu mengirim pesan tetapi jika Anda tidak menangkapnya, itu akan menimbulkan kesalahan pengecualian yang tidak tertangani kepada pengguna.
sumber
Saat melempar kembali pengecualian, kata kunci melempar dengan sendirinya. Ini akan membuang pengecualian yang tertangkap dan masih dapat menggunakan pelacakan tumpukan untuk melihat dari mana asalnya.
melakukan ini akan menyebabkan pelacakan tumpukan berakhir di pernyataan catch. (hindari ini)
sumber
n pengalaman saya, saya merasa cocok untuk menangkap pengecualian ketika saya tahu saya akan membuatnya. Misalnya ketika saya berada di aplikasi web dan saya melakukan Response.Redirect, saya tahu saya akan mendapatkan System.ThreadAbortException. Karena memang disengaja saya hanya menangkap untuk jenis tertentu dan menelannya saja.
sumber
Saya sangat setuju dengan aturan:
Alasannya adalah:
ForceAssert.AlwaysAssert adalah cara pribadi saya untuk Trace.Assert terlepas dari apakah makro DEBUG / TRACE ditentukan.
Siklus pengembangan mungkin: Saya melihat dialog Assert yang jelek atau orang lain mengeluh kepada saya tentang hal itu, lalu saya kembali ke kode dan mencari tahu alasan untuk mengajukan pengecualian dan memutuskan bagaimana memprosesnya.
Dengan cara ini saya dapat menuliskan kode MY dalam waktu singkat dan melindungi saya dari domain yang tidak dikenal, tetapi selalu diperhatikan jika terjadi hal-hal abnormal, dengan cara ini sistem menjadi aman dan lebih aman.
Saya tahu banyak dari Anda tidak akan setuju dengan saya karena pengembang harus mengetahui setiap detail kodenya, terus terang, saya juga seorang purist di masa lalu. Tapi sekarang saya belajar bahwa kebijakan di atas lebih pragmatis.
Untuk kode WinForms, aturan emas yang selalu saya patuhi adalah:
ini akan melindungi UI Anda agar selalu dapat digunakan.
Untuk kinerja hit, penalti kinerja hanya terjadi ketika kode mencapai tangkapan, menjalankan kode percobaan tanpa pengecualian aktual yang dimunculkan tidak berpengaruh signifikan.
Pengecualian harus terjadi dengan sedikit kesempatan, jika tidak maka bukan pengecualian.
sumber
Anda harus memikirkan pengguna. Aplikasi crash adalah terakhirhal yang diinginkan pengguna. Oleh karena itu, setiap operasi yang dapat gagal harus memiliki blok coba tangkap di tingkat ui. Tidak perlu menggunakan try catch di setiap metode, tetapi setiap kali pengguna melakukan sesuatu, ia harus dapat menangani pengecualian umum. Itu sama sekali tidak membebaskan Anda dari memeriksa semuanya untuk mencegah pengecualian pada kasus pertama, tetapi tidak ada aplikasi kompleks tanpa bug dan OS dapat dengan mudah menambahkan masalah yang tidak terduga, oleh karena itu Anda harus mengantisipasi hal yang tidak terduga dan memastikan jika pengguna ingin menggunakannya operasi tidak akan ada kehilangan data karena aplikasi mogok. Tidak perlu pernah membiarkan aplikasi Anda mogok, jika Anda menemukan pengecualian, itu tidak akan pernah dalam keadaan tidak pasti dan pengguna SELALU merasa tidak nyaman oleh kerusakan. Meskipun pengecualian ada di tingkat paling atas, tidak mogok berarti pengguna dapat dengan cepat mereproduksi pengecualian atau setidaknya merekam pesan kesalahan dan oleh karena itu sangat membantu Anda untuk memperbaiki masalah. Tentu lebih dari sekadar mendapatkan pesan kesalahan sederhana dan kemudian hanya melihat dialog kesalahan jendela atau sesuatu seperti itu.
Itulah mengapa Anda TIDAK PERNAH menjadi sombong dan berpikir bahwa aplikasi Anda tidak memiliki bug, itu tidak dijamin. Dan ini adalah upaya yang sangat kecil untuk membungkus beberapa blok coba tangkap tentang kode yang sesuai dan menampilkan pesan kesalahan / mencatat kesalahan.
Sebagai pengguna, saya pasti sangat kesal setiap kali alis atau aplikasi kantor atau apa pun mogok. Jika pengecualian sangat tinggi sehingga aplikasi tidak dapat melanjutkan, lebih baik menampilkan pesan itu dan memberi tahu pengguna apa yang harus dilakukan (mulai ulang, perbaiki beberapa pengaturan os, laporkan bug, dll.) Daripada hanya crash dan hanya itu.
sumber