Mengapa menangkap dan memikirkan kembali pengecualian dalam C #?

557

Saya sedang melihat artikel C # - Data Transfer Object pada DTO serializable.

Artikel ini termasuk potongan kode ini:

public static string SerializeDTO(DTO dto) {
    try {
        XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
        StringWriter sWriter = new StringWriter();
        xmlSer.Serialize(sWriter, dto);
        return sWriter.ToString();
    }
    catch(Exception ex) {
        throw ex;
    }
}

Sisa artikel ini terlihat waras dan masuk akal (untuk noob), tapi coba-coba-lempar melempar WtfException ... Bukankah ini sama dengan tidak menangani pengecualian sama sekali?

Jadi:

public static string SerializeDTO(DTO dto) {
    XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
    StringWriter sWriter = new StringWriter();
    xmlSer.Serialize(sWriter, dto);
    return sWriter.ToString();
}

Atau apakah saya melewatkan sesuatu yang mendasar tentang penanganan kesalahan di C #? Ini hampir sama dengan Java (minus pengecualian yang diperiksa), bukan? ... Yaitu, mereka berdua menyempurnakan C ++.

Pertanyaan Stack Overflow Perbedaan antara melempar kembali parameter-less catch dan tidak melakukan apa-apa? tampaknya mendukung pendapat saya bahwa try-catch-throw adalah-no-op.


EDIT:

Hanya untuk meringkas bagi siapa saja yang menemukan utas ini di masa depan ...

TIDAK

try {
    // Do stuff that might throw an exception
}
catch (Exception e) {
    throw e; // This destroys the strack trace information!
}

Informasi jejak tumpukan dapat menjadi sangat penting untuk mengidentifikasi akar penyebab masalah!

MELAKUKAN

try {
    // Do stuff that might throw an exception
}
catch (SqlException e) {
    // Log it
    if (e.ErrorCode != NO_ROW_ERROR) { // filter out NoDataFound.
        // Do special cleanup, like maybe closing the "dirty" database connection.
        throw; // This preserves the stack trace
    }
}
catch (IOException e) {
    // Log it
    throw;
}
catch (Exception e) {
    // Log it
    throw new DAOException("Excrement occurred", e); // wrapped & chained exceptions (just like java).
}
finally {
    // Normal clean goes here (like closing open files).
}

Tangkap pengecualian yang lebih spesifik sebelum yang kurang spesifik (seperti Java).


Referensi:

corlettk
sumber
8
Ringkasan yang bagus; poin tambahan untuk menyertakan blok akhirnya.
Fredrik Mörk
saya ingin menambahkan bahwa Anda dapat menggunakan "lemparan;" untuk menjadi lebih membantu dengan menambahkan parameter yang dikirim ke metode dalam koleksi e.Data sebelum "throw;" pernyataan
Michael Bahig
@MickTheWarMachineDesigner (dan pelukis paruh waktu). Hah? Anda sedang berbicara menangani pengecualian Microshite Suckwell (mungkin 2005 dan seterusnya, untuk semua yang saya tahu). Saya berbicara tentang penanganan pengecualian secara umum. Dan ya, saya sudah belajar beberapa sejak saya memposting ini SEKITAR EMPAT TAHUN YANG LALU .... Tapi ya, saya akui bahwa Anda memiliki poin yang valid, tetapi saya pikir Anda telah melewatkan poin sebenarnya; Jika Anda mengerti maksud saya? Pertanyaan ini adalah tentang penanganan perkecualian yang GENERALISASI dalam C #; dan lebih khusus tentang memikirkan kembali pengecualian ... dari SEMUA jenis. Keren?
corlettk
Harap pertimbangkan untuk memindahkan bagian edit ringkasan di pertanyaan Anda ke jawabannya sendiri. Untuk alasannya, lihat Mengedit jawaban sendiri dari pertanyaan dan Jawab tertanam dalam pertanyaan .
DavidRR
2
Adakah yang tidak memperhatikan bagian "Terjadi kotoran"? kedengarannya seperti kode untuk kotoran!
Jason Loki Smith

Jawaban:

430

Pertama; cara kode dalam artikel itu melakukannya adalah jahat. throw exakan mengatur ulang tumpukan panggilan dalam pengecualian ke titik di mana pernyataan melempar ini adalah; kehilangan informasi tentang di mana pengecualian sebenarnya dibuat.

Kedua, jika Anda hanya menangkap dan melempar kembali seperti itu, saya tidak melihat nilai tambah, contoh kode di atas akan sama baiknya (atau, mengingat throw exbitnya, bahkan lebih baik) tanpa try-catch.

Namun, ada beberapa kasus di mana Anda mungkin ingin menangkap dan memikirkan kembali pengecualian. Penebangan bisa menjadi salah satunya:

try 
{
    // code that may throw exceptions    
}
catch(Exception ex) 
{
    // add error logging here
    throw;
}
Fredrik Mörk
sumber
6
@ Frick, hanya fyi (meskipun Anda mungkin tahu) jika Anda tidak akan menggunakan exobjek itu, maka tidak perlu untuk instantiate.
Eoin Campbell
78
@Eoin: Jika tidak dipakai maka akan lebih sulit untuk mencatatnya.
Sam Axe
30
Yap, saya pikir "jahat" adalah tentang benar ... pertimbangkan kasus pengecualian pointer nol yang dilemparkan di suatu tempat dari sejumlah besar kode. Pesannya adalah vanilla, tanpa jejak tumpukan yang tersisa dengan "ada sesuatu yang nol di suatu tempat". TIDAK baik ketika produksi mati; dan Anda TIDAK punya menit atau kurang untuk menyelesaikan masalah flamin, dan singkirkan atau perbaiki ... Penanganan pengecualian yang baik bernilai emas.
corlettk
4
Apakah itu berlaku untuk Java juga ... "throw" vs. "throw ex"?
JasonStoltz
8
@ Jason, lihat pertanyaan ini . Di Jawa, throw extidak me-restart stacktrace.
Matthew Flaschen
117

Jangan lakukan ini,

try 
{
...
}
catch(Exception ex)
{
   throw ex;
}

Anda akan kehilangan informasi jejak tumpukan ...

Baik lakukan,

try { ... }
catch { throw; }

ATAU

try { ... }
catch (Exception ex)
{
    throw new Exception("My Custom Error Message", ex);
}

Salah satu alasan Anda mungkin ingin melakukan rethrow adalah jika Anda menangani pengecualian yang berbeda, misalnya

try
{
   ...
}
catch(SQLException sex)
{
   //Do Custom Logging 
   //Don't throw exception - swallow it here
}
catch(OtherException oex)
{
   //Do something else
   throw new WrappedException("Other Exception occured");
}
catch
{
   System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
   throw; //Chuck everything else back up the stack
}
Eoin Campbell
sumber
7
Mengapa tidak tinggalkan tangkapan {throw} sama sekali?
AnthonyWJones
3
masih ada nilai dalam meninggalkan tangkapan {throw; } di bagian bawah daftar tangkapan jenis pengecualian khusus dengan alasan itu membuktikan penulis mempertimbangkan kasusnya, meskipun komentar mungkin cukup memadai. Tidak menebak kapan Anda membaca kode adalah hal yang baik.
annakata
87
Untuk beberapa alasan, nama SQLException mengganggu saya.
Michael Myers
13
Tangkapan itu (Pengecualian) {throw new Exception (...)} adalah sesuatu yang tidak boleh , pernah, pernah Anda lakukan, hanya karena Anda mengaburkan informasi pengecualian dan membuat penyaringan pengecualian lebih jauh ke atas tumpukan panggilan menjadi sangat sulit. Satu-satunya waktu Anda harus menangkap satu jenis pengecualian dan melemparkan yang lain adalah ketika Anda menerapkan lapisan abstraksi dan Anda perlu mengubah jenis pengecualian khusus penyedia (misalnya SqlException versus XmlException) menjadi yang lebih umum (misalnya DataLoadingException).
jammycakes
3
@dark_perfect Anda harus memeriksa argumen itu di muka, di awal metode dan membuang ArgumentNullException di sana (gagal cepat).
Andrei Bozantan
56

C # (sebelum C # 6) tidak mendukung CIL "pengecualian yang difilter", yang dilakukan VB, jadi di C # 1-5 satu alasan untuk melempar kembali pengecualian adalah karena Anda tidak memiliki informasi yang cukup pada saat penangkapan () untuk menentukan apakah Anda ingin menangkap pengecualian.

Misalnya, di VB bisa Anda lakukan

Try
 ..
Catch Ex As MyException When Ex.ErrorCode = 123
 .. 
End Try

... yang tidak akan menangani MyExceptions dengan nilai ErrorCode yang berbeda. Di C # sebelum v6, Anda harus menangkap dan melempar kembali MyException jika ErrorCode bukan 123:

try 
{
   ...
}
catch(MyException ex)
{
    if (ex.ErrorCode != 123) throw;
    ...
}

Karena C # 6.0 Anda dapat memfilter seperti halnya dengan VB:

try 
{
  // Do stuff
} 
catch (Exception e) when (e.ErrorCode == 123456) // filter
{
  // Handle, other exceptions will be left alone and bubble up
}
bzlm
sumber
2
Dave, tetapi (setidaknya dalam java) Anda tidak akan melempar MyException "generik", Anda akan menentukan jenis pengecualian SPESIFIK dan membuangnya, memungkinkannya untuk dibedakan berdasarkan jenis di blok tangkap ... Tapi ya , jika Anda bukan arsitek pengecualian (saya berpikir SQLException JDBC (Java lagi) di sini, yang menjijikkan generik, dan memperlihatkan metode getErrorCode () ... Hmmm ... Anda ada benarnya, hanya saja saya pikir ada cara yang lebih baik untuk melakukannya, di mana mungkin Ceria Mate saya menghargai waktu Anda, banyak Keith....
corlettk
1
Nah, pertanyaannya adalah "Mengapa menangkap dan menggabungkan kembali Pengecualian dalam C #?", Dan ini adalah jawabannya. =] ... dan bahkan dengan pengecualian khusus, Filter Pengecualian masuk akal: pertimbangkan kasus di mana Anda, katakanlah, menangani SqlTimeoutException dan SqlConnectionResetException, yang keduanya merupakan SqlException. Filter Pengecualian memungkinkan Anda menangkap SqlException hanya ketika salah satu dari dua ini, jadi alih-alih mengacaukan coba / tangkapan Anda dengan penanganan yang sama untuk kedua ini, Anda bisa "menangkap SqlException ex saat mantan adalah SqlTimeoutException Atau ex adalah SqlConnectionResetException". (Aku bukan Dave btw)
bzlm
3
Pengecualian yang difilter datang dalam C # 6!
Sir Crispalot
14

Alasan utama saya memiliki kode seperti:

try
{
    //Some code
}
catch (Exception e)
{
    throw;
}

Jadi saya dapat memiliki breakpoint di tangkapan, yang memiliki objek pengecualian yang dipakai. Saya melakukan ini banyak saat mengembangkan / debugging. Tentu saja, kompiler memberi saya peringatan pada semua e yang tidak digunakan, dan idealnya mereka harus dihapus sebelum rilis rilis.

Mereka bagus selama debugging.

Peter Mortensen
sumber
1
Ya, aku akan membayar satu itu, tapi ya, Anda tidak akan ingin melihat bahwa dalam menerbitkan kode ... ergo: Saya akan malu untuk mempublikasikannya ;-)
corlettk
25
Sebenarnya, ini tidak perlu - di Visual Studio Anda dapat mengatur debugger untuk istirahat ketika pengecualian dilemparkan dan memunculkan detail pengecualian di jendela inspektur untuk Anda.
jammycakes
8
Jika Anda ingin menggunakan beberapa kode HANYA selama debugging, gunakan #jika DEBUG ... #endif, dan Anda tidak perlu menghapus baris-baris ini
Michael Freidgeim
1
Ya, saya sendiri pernah melakukannya beberapa kali. Sesekali orang akan melarikan diri ke rilis. @ Jammycakes Masalah dengan istirahat Visual Studio pada pengecualian adalah, kadang-kadang pengecualian yang saya inginkan bukan satu-satunya (atau bahkan hanya satu dari jenisnya) yang dilemparkan. Masih tidak tahu kondisi break point dengan "break jika dilewati oleh pengecualian". Sampai saat ini, ini akan tetap berguna. Michael Freidgeim: #if DEBUGsekitar KEDUA try {dan } catch () {...}agak berantakan dan, terus terang, membuat saya mual ... Pra-prosesor, secara umum, bukan teman saya.
11

Alasan yang sah untuk mengkaji ulang pengecualian dapat karena Anda ingin menambahkan informasi ke pengecualian, atau mungkin membungkus pengecualian asli dalam salah satu buatan Anda sendiri:

public static string SerializeDTO(DTO dto) {
  try {
      XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
      StringWriter sWriter = new StringWriter();
      xmlSer.Serialize(sWriter, dto);
      return sWriter.ToString();
  }
  catch(Exception ex) {
    string message = 
      String.Format("Something went wrong serializing DTO {0}", DTO);
    throw new MyLibraryException(message, ex);
  }
}
edosoft
sumber
Terima kasih, ya, membungkus pengecualian (terutama yang dirantai) benar-benar waras ... apa yang tidak waras adalah menangkap pengecualian hanya agar Anda dapat membuang jejak tumpukan, atau lebih buruk, memakannya.
corlettk
10

Bukankah ini sama dengan tidak menangani pengecualian sama sekali?

Tidak persis sama, itu tidak sama. Ini mengatur ulang stacktrace pengecualian. Meskipun saya setuju bahwa ini mungkin kesalahan, dan dengan demikian contoh kode yang buruk.

Arjan Einbu
sumber
8

Anda tidak ingin membuang mantan - karena ini akan kehilangan tumpukan panggilan. Lihat Penanganan Pengecualian (MSDN).

Dan ya, coba ... tangkapan tidak melakukan hal yang berguna (selain kehilangan tumpukan panggilan - jadi sebenarnya lebih buruk - kecuali karena alasan tertentu Anda tidak ingin membuka informasi ini).

Duncan
sumber
Anda tidak kehilangan seluruh tumpukan panggilan saat Anda menggunakan throw ex, Anda hanya kehilangan bagian dari tumpukan panggilan dari titik di mana pengecualian terjadi lebih tinggi di tumpukan panggilannya. Tetapi Anda mempertahankan tumpukan panggilan dari metode yang melemparkan pengecualian ke tempat klien memanggilnya. Sebenarnya mungkin ada kasus penggunaan di mana Anda akan menggunakannya, atau orang baik di Microsoft tidak akan mengizinkannya. Yang mengatakan, saya belum menggunakannya. Masalah lain yang perlu diingat adalah bahwa melempar pengecualian itu mahal. Lakukan saja untuk alasan yang sangat bisa dibenarkan. Penebangan Saya pikir akan dibenarkan, dll.
Charles Owen
5

Suatu hal yang belum disebutkan orang adalah bahwa sementara .NET bahasa tidak benar-benar membuat perbedaan yang tepat, pertanyaan apakah seseorang harus mengambil tindakan ketika pengecualian terjadi, dan apakah seseorang akan menyelesaikannya , sebenarnya adalah pertanyaan yang berbeda. Ada banyak kasus di mana seseorang harus mengambil tindakan berdasarkan pengecualian yang tidak memiliki harapan untuk diselesaikan, dan ada beberapa kasus di mana semua yang diperlukan untuk "menyelesaikan" pengecualian adalah untuk melepaskan tumpukan ke titik tertentu - tidak diperlukan tindakan lebih lanjut .

Karena kebijaksanaan umum bahwa seseorang seharusnya hanya "menangkap" hal-hal yang dapat "ditangani", banyak kode yang harus mengambil tindakan ketika pengecualian terjadi, tidak. Misalnya, banyak kode akan memperoleh kunci, menempatkan objek yang dijaga "sementara" ke dalam keadaan yang melanggar invariannya, kemudian meletakkannya objek ke keadaan yang sah, dan kemudian melepaskan kunci kembali sebelum orang lain dapat melihat objek. Jika pengecualian terjadi ketika objek dalam keadaan berbahaya-tidak valid, praktik umum adalah melepaskan kunci dengan objek masih dalam keadaan itu. Pola yang jauh lebih baik adalah memiliki pengecualian yang terjadi saat objek berada dalam kondisi "berbahaya" yang secara tegas membatalkan kunci sehingga setiap upaya di masa depan untuk mendapatkannya akan segera gagal.

Dalam sebagian besar bahasa .NET, satu-satunya cara kode mengambil tindakan berdasarkan pengecualian adalah dengan catchmelakukannya (meskipun ia tahu itu tidak akan menyelesaikan pengecualian), lakukan tindakan yang dimaksud dan kemudian kembali throw). Pendekatan lain yang mungkin jika kode tidak peduli tentang pengecualian apa yang dilemparkan adalah menggunakan okbendera dengan try/finallyblok; atur okbendera falsesebelum blok, dan truesebelum blok keluar, dan sebelum apa pun returnyang ada di dalam blok. Kemudian, di dalam finally, asumsikan bahwa jika oktidak disetel, pengecualian harus terjadi. Pendekatan semacam itu secara semantik lebih baik daripada catch/ throw, tetapi jelek dan kurang bisa dipertahankan.

supercat
sumber
5

Ini bisa berguna ketika fungsi pemrograman Anda untuk perpustakaan atau dll.

Struktur rethrow ini dapat digunakan untuk mengatur ulang tumpukan panggilan dengan sengaja sehingga alih-alih melihat pengecualian yang dilemparkan dari fungsi individual di dalam fungsi, Anda mendapatkan pengecualian dari fungsi itu sendiri.

Saya pikir ini hanya digunakan sehingga pengecualian yang dilemparkan lebih bersih dan tidak masuk ke "akar" perpustakaan.

Jackson Tarisa
sumber
3

Salah satu alasan yang memungkinkan untuk melakukan throw-throw adalah untuk menonaktifkan filter pengecualian yang lebih dalam dari stack agar tidak difilter ( tautan lama acak ). Tapi tentu saja, jika itu niatnya, akan ada komentar di sana yang mengatakannya.

Brian
sumber
Saya tidak mendapatkan apa yang Anda maksudkan sampai saya membaca tautannya ... dan saya masih tidak yakin apa yang sedang Anda bahas ... saya benar-benar tidak terbiasa dengan VB.NET. Saya pikir ini menghasilkan jumlah yang dilaporkan "tidak konsisten", kan? ... Saya penggemar besar metode statis .. selain sederhana, ada sedikit kemungkinan inkonsistensi jika Anda memisahkan pengaturan atribut dari kode. yang melakukan pekerjaan yang sebenarnya. Tumpukan adalah "pembersihan sendiri".
corlettk
3
Orang-orang berharap ketika mereka menulis "coba {Foo ();} akhirnya {Bar ();}" bahwa tidak ada yang berjalan antara Foo dan Bar. Tetapi ini tidak benar; jika penelepon Anda menambahkan filter pengecualian, dan tidak ada 'tangkapan', dan Foo () melempar, maka beberapa kode acak lain dari penelepon Anda akan berjalan sebelum akhirnya (Bar) Anda berjalan. Ini sangat buruk jika Anda telah melanggar invarian atau peningkatan keamanan, berharap bahwa mereka akan 'segera' dikembalikan ke normal pada akhirnya dan tidak ada kode lain yang akan melihat perubahan sementara.
Brian
3

Itu tergantung apa yang Anda lakukan di blok tangkap, dan jika Anda ingin meneruskan kesalahan ke kode panggilan atau tidak.

Anda mungkin mengatakan Catch io.FileNotFoundExeption exdan kemudian menggunakan jalur file alternatif atau semacamnya, tetapi masih melempar kesalahan.

Juga melakukan Throwalih - alih Throw Exmemungkinkan Anda menyimpan jejak tumpukan penuh. Throw ex me-restart jejak stack dari pernyataan throw (saya harap itu masuk akal).

Pondidum
sumber
3

Sementara banyak dari jawaban lain memberikan contoh yang bagus tentang mengapa Anda mungkin ingin menangkap kembali perkecualian, tidak ada yang tampaknya menyebutkan skenario 'akhirnya'.

Contoh dari ini adalah di mana Anda memiliki metode di mana Anda mengatur kursor (misalnya ke kursor tunggu), metode ini memiliki beberapa titik keluar (misalnya jika () kembali;) dan Anda ingin memastikan kursor diatur ulang di akhir metode.

Untuk melakukan ini, Anda dapat membungkus semua kode dengan mencoba / menangkap / akhirnya. Pada akhirnya atur kursor kembali ke kursor kanan. Agar Anda tidak mengubur pengecualian yang valid, kembalikan di tangkapan.

try
{
    Cursor.Current = Cursors.WaitCursor;
    // Test something
    if (testResult) return;
    // Do something else
}
catch
{
    throw;
}
finally
{
     Cursor.Current = Cursors.Default;
}
statler
sumber
1
Apakah catchmerupakan bagian wajib dari try...finallysejarah, atau apakah itu memainkan peran fungsional dalam contoh ini? - Saya baru saja memeriksa ulang, dan saya dapat menggunakan try {} finally {}tanpa catch catch block sama sekali.
Sebi
2

Pada contoh dalam kode yang Anda posting ada, pada kenyataannya, tidak ada gunanya menangkap pengecualian karena tidak ada yang dilakukan pada tangkapan itu hanya ulang-ulang, pada kenyataannya itu lebih berbahaya daripada baiknya sebagai tumpukan panggilan hilang .

Namun, Anda akan mendapatkan pengecualian untuk melakukan beberapa logika (misalnya menutup koneksi sql dari kunci file, atau hanya beberapa logging) dalam hal pengecualian melemparkannya kembali ke kode panggilan untuk menangani. Ini akan lebih umum di lapisan bisnis daripada kode ujung depan karena Anda mungkin ingin pembuat kode mengimplementasikan lapisan bisnis Anda untuk menangani pengecualian.

Untuk mengulangi kembali meskipun TIDAK ada gunanya menangkap pengecualian pada contoh yang Anda posting. JANGAN lakukan seperti itu!

Sheff
sumber
1

Maaf, tetapi banyak contoh sebagai "desain yang ditingkatkan" masih berbau mengerikan atau bisa sangat menyesatkan. Telah mencoba {} catch {log; melempar} sama sekali tidak ada gunanya. Pencatatan pengecualian harus dilakukan di tempat sentral di dalam aplikasi. Pengecualian memunculkan stacktrace, mengapa tidak mencatatnya di suatu tempat dan dekat dengan perbatasan sistem?

Perhatian harus digunakan ketika Anda membuat serial konteks Anda (yaitu DTO dalam satu contoh yang diberikan) hanya ke dalam pesan log. Ini dapat dengan mudah berisi informasi sensitif yang mungkin tidak ingin menjangkau semua orang yang dapat mengakses file log. Dan jika Anda tidak menambahkan informasi baru ke pengecualian, saya benar-benar tidak melihat titik pembungkus pengecualian. Java tua yang baik memiliki beberapa poin untuk itu, itu membutuhkan penelepon untuk mengetahui pengecualian apa yang harus diharapkan seseorang kemudian memanggil kode. Karena Anda tidak memiliki ini dalam. NET, pembungkus tidak ada gunanya pada setidaknya 80% dari kasus yang saya lihat.


sumber
Terima kasih atas pemikiran Anda, Joe. Di Jawa (dan C #, saya kira) saya akan senang melihat anotasi tingkat kelas @FaultBoundary yang memaksa SEMUA pengecualian (termasuk jenis-jenis pengecualian yang tidak dicentang) untuk ditangkap-atau-dinyatakan-akan-dibuang. Saya akan menggunakan anotasi ini pada antarmuka publik dari setiap lapisan arsitektur. Jadi antarmuka @FaultBoundary ThingDAO tidak akan dapat membocorkan detail implementasi seperti SQLExceptions, NPE, atau AIOB. Sebaliknya stacktrace "kausal" akan dicatat dan DAOSystemException akan dibuang ... Saya mendefinisikan pengecualian Sistem sebagai "fatal permanen".
corlettk
5
Ada banyak alasan untuk menangkap, mencatat, lalu melakukan rethrow. Khususnya jika metode dengan catch log memiliki informasi yang hilang setelah Anda keluar dari metode. Kesalahan mungkin ditangani kemudian tetapi tidak dicatat, dan Anda kehilangan informasi tentang cacat pada sistem.
Andy
1
Di sinilah properti Data dari kelas Exception berguna - menangkap semua informasi lokal untuk logging generik. Artikel ini awalnya menarik perhatian saya: blog.abodit.com/2010/03/...
McGuireV10
1

Selain apa yang dikatakan orang lain, lihat jawaban saya untuk pertanyaan terkait yang menunjukkan bahwa penangkapan dan pemindahan kembali bukan larangan (ada dalam VB, tetapi beberapa kode bisa C # dipanggil dari VB).

erikkallen
sumber
Meskipun tautan ini dapat menjawab pertanyaan, lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini dan memberikan tautan untuk referensi. Jawaban hanya tautan dapat menjadi tidak valid jika halaman tertaut berubah. - Dari Ulasan
LHIOUI
@ HamzaLH, saya setuju bahwa itu bukan jawaban yang ditulis dengan baik, tetapi memiliki informasi, berbeda dengan jawaban lain dan suara positif. Jadi saya tidak mengerti, mengapa Anda menyarankan untuk menghapusnya? "Jawaban singkat yang ada di topik dan memberikan solusi masih merupakan jawaban." Dari meta.stackexchange.com/questions/226258/…
Michael Freidgeim
ini hanya jawaban
tautan
1. Jawaban khusus tautan harus diubah menjadi komentar, bukan dihapus. 2. Ini merujuk ke pertanyaan SO lainnya, bukan ke situs eksternal, yang dianggap lebih kecil kemungkinannya rusak seiring waktu. 3. Ini memiliki beberapa deskripsi tambahan, yang membuatnya bukan "hanya tautan" - lihat meta.stackexchange.com/questions/225370/…
Michael Freidgeim
1

Sebagian besar jawaban berbicara tentang skenario catch-log-rethrow.

Alih-alih menuliskannya dalam kode Anda, pertimbangkan untuk menggunakan AOP, khususnya Postsharp.Diagnostic.Toolkit dengan OnExceptionOptions, SertakanParameterValue dan Sertakan Dokumen Ini

Michael Freidgeim
sumber
Meskipun tautan ini dapat menjawab pertanyaan, lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini dan memberikan tautan untuk referensi. Jawaban hanya tautan dapat menjadi tidak valid jika halaman tertaut berubah. - Dari Ulasan
Tony Dong
@ TonyDong, saya setuju bahwa itu bukan jawaban yang ditulis dengan baik, tetapi memiliki informasi, berbeda dengan jawaban lain dan suara positif. Jadi saya tidak mengerti, mengapa Anda menyarankan untuk menghapusnya? BTW, tautan 5 tahun kemudian masih valid. "Jawaban singkat yang ada di topik dan memberikan solusi masih merupakan jawaban." Dari meta.stackexchange.com/questions/226258/…
Michael Freidgeim
Stackoverflow hanya memiliki saran ini.
Tony Dong
@ TonyDong, jika jawabannya tidak sepenuhnya sia-sia, Anda harus memilih "Terlihat OK"
Michael Freidgeim
0

Rethrowing exception via throw berguna ketika Anda tidak memiliki kode tertentu untuk menangani pengecualian saat ini, atau dalam kasus ketika Anda memiliki logika untuk menangani kasus kesalahan tertentu tetapi ingin melewatkan semua yang lain.

Contoh:

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException)
{
    if (numberText.ToLowerInvariant() == "nothing")
    {
        Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
    }
    else
    {
        throw;
    }
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

Namun, ada juga cara lain untuk melakukan ini, menggunakan klausa kondisional di blok tangkap:

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException) when (numberText.ToLowerInvariant() == "nothing")
{
    Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

Mekanisme ini lebih efisien daripada melemparkan kembali pengecualian karena runtime .NET tidak harus membangun kembali objek pengecualian sebelum melemparkan kembali.

Arsen Khachaturyan
sumber