Ada beberapa postingan yang menanyakan apa perbedaan keduanya.
(Kenapa aku harus menyebutkan ini ...)
Tetapi pertanyaan saya berbeda dengan cara yang saya sebut "lempar mantan" dalam metode penanganan kesalahan seperti dewa lainnya .
public class Program {
public static void Main(string[] args) {
try {
// something
} catch (Exception ex) {
HandleException(ex);
}
}
private static void HandleException(Exception ex) {
if (ex is ThreadAbortException) {
// ignore then,
return;
}
if (ex is ArgumentOutOfRangeException) {
// Log then,
throw ex;
}
if (ex is InvalidOperationException) {
// Show message then,
throw ex;
}
// and so on.
}
}
Jika try & catch
digunakan dalam Main
, maka saya akan gunakan throw;
untuk rethrow kesalahan. Namun dalam kode sederhana di atas, semua pengecualian harus dilaluiHandleException
Apakah throw ex;
memiliki efek yang sama dengan menelepon throw
saat dipanggil di dalam HandleException
?
c#
.net
exception
exception-handling
dance2die
sumber
sumber
Jawaban:
Ya, ada perbedaan;
throw ex
ulang jejak tumpukan (sehingga kesalahan Anda tampaknya berasal dariHandleException
)throw
tidak - pelaku asli akan dilestarikan.sumber
(Saya diposting sebelumnya, dan @Marc Gravell telah mengoreksi saya)
Inilah demonstrasi perbedaannya:
dan inilah outputnya:
Anda dapat melihat bahwa di Pengecualian 1, jejak tumpukan kembali ke
DivByZero()
metode, sedangkan di Pengecualian 2 tidak.Catat, bahwa nomor baris yang ditampilkan
ThrowException1()
danThrowException2()
adalah nomor baristhrow
pernyataan, bukan nomor baris panggilanDivByZero()
, yang mungkin masuk akal sekarang karena saya memikirkannya sedikit ...Output dalam mode Release
Pengecualian 1:
Pengecualian 2:
Apakah ini mempertahankan stackTrace asli hanya dalam mode debug?
sumber
DevideByZero
, sehingga jejak stack IS sama. mungkin Anda harus memposting ini sebagai pertanyaan sendiriJawaban lainnya sepenuhnya benar, tetapi jawaban ini memberikan beberapa detali ekstra, saya pikir.
Pertimbangkan contoh ini:
Jika Anda menghapus komentar
throw arithExc;
baris, output Anda adalah:Tentu saja, Anda telah kehilangan informasi tentang di mana pengecualian itu terjadi. Jika sebaliknya Anda menggunakan
throw;
garis, inilah yang Anda dapatkan:Ini jauh lebih baik, karena sekarang Anda melihat bahwa itu adalah
Program.Div
metode yang menyebabkan masalah Anda. Tetapi masih sulit untuk melihat apakah masalah ini berasal dari baris 35 atau baris 37 ditry
blok.Jika Anda menggunakan alternatif ketiga, membungkus pengecualian luar, Anda tidak kehilangan informasi:
Khususnya Anda dapat melihat bahwa baris 35 yang mengarah ke masalah. Namun, ini mengharuskan orang untuk mencari
InnerException
, dan rasanya agak tidak langsung untuk menggunakan pengecualian dalam kasus sederhana.Dalam posting blog ini mereka mempertahankan nomor baris (garis blok coba) dengan memanggil (melalui refleksi)
internal
metode intensiInternalPreserveStackTrace()
padaException
objek. Tetapi tidak baik menggunakan refleksi seperti itu (.NET Framework mungkin mengubahinternal
anggota mereka suatu hari tanpa peringatan).sumber
mari kita pahami perbedaan antara melempar dan melempar mantan. Saya mendengar bahwa dalam banyak wawancara. Net, pertanyaan umum ini ditanyakan.
Hanya untuk memberikan gambaran dari kedua istilah ini, lempar dan lempar keduanya digunakan untuk memahami di mana pengecualian telah terjadi. Lempar ex menulis ulang jejak stack pengecualian terlepas di mana sebenarnya telah dibuang.
Mari kita pahami dengan sebuah contoh.
Mari kita pahami dulu Throw.
output di atas di bawah ini.
menunjukkan hierarki lengkap dan nama metode di mana sebenarnya pengecualian telah dilempar .. itu adalah M2 -> M2. bersama dengan nomor baris
Kedua .. mari kita pahami dengan melemparkan mantan. Cukup ganti throw dengan throw ex di M2 metode catch block. seperti di bawah ini.
output dari throw ex code adalah seperti di bawah ini ..
Anda dapat melihat perbedaan dalam output .. throw ex hanya mengabaikan semua hierarki sebelumnya dan me-reset jejak stack dengan garis / metode di mana throw ex ditulis.
sumber
Ketika Anda melakukannya
throw ex
, pengecualian yang dilemparkan itu menjadi yang "asli". Jadi semua jejak stack sebelumnya tidak akan ada.Jika Anda melakukannya
throw
, pengecualian hanya turun dan Anda akan mendapatkan jejak tumpukan penuh.sumber
Tidak, ini akan menyebabkan pengecualian memiliki jejak tumpukan yang berbeda. Hanya menggunakan objek
throw
tanpa pengecualian dicatch
handler akan meninggalkan jejak stack tidak berubah.Anda mungkin ingin mengembalikan boolean dari HandleException apakah pengecualian akan dipulihkan atau tidak.
sumber
MSDN adalah singkatan :
sumber
Lihat di sini: http://blog-mstechnology.blogspot.de/2010/06/throw-vs-throw-ex.html
Lempar :
Itu menjaga informasi Stack dengan Exception
Ini disebut sebagai "Rethrow"
Jika ingin melempar pengecualian baru,
Lempar Mantan :
Itu Tidak Akan Mengirimkan informasi Stack dengan Pengecualian
Ini disebut sebagai "Breaking the Stack"
Jika ingin melempar pengecualian baru,
sumber
Untuk memberi Anda perspektif yang berbeda tentang ini, menggunakan lemparan sangat berguna jika Anda menyediakan API untuk klien dan Anda ingin memberikan informasi jejak tumpukan verbose untuk pustaka internal Anda. Dengan menggunakan lemparan di sini, saya akan mendapatkan jejak stack dalam hal ini perpustakaan System.IO.File untuk File.Delete. Jika saya menggunakan throw ex, maka informasi itu tidak akan diteruskan ke handler saya.
sumber
jika semua Baris 1, 2 dan 3 dikomentari - Keluaran - dalam ex
jika semua Baris 2 dan 3 dikomentari - Output - inner ex System.DevideByZeroException: {"Mencoba untuk membagi dengan nol."} ---------
jika semua Baris 1 dan 2 dikomentari - Output - inner ex System.Exception: bagi dengan 0 ----
jika semua Baris 1 dan 3 dikomentari - Output - inner ex System.DevideByZeroException: {"Mencoba untuk membagi dengan nol."} ---------
dan StackTrace akan diatur ulang jika membuang mantan;
sumber