Saya menemukan fitur baru ini di C # yang memungkinkan penangan tangkapan untuk mengeksekusi ketika kondisi tertentu terpenuhi.
int i = 0;
try
{
throw new ArgumentNullException(nameof(i));
}
catch (ArgumentNullException e)
when (i == 1)
{
Console.WriteLine("Caught Argument Null Exception");
}
Saya mencoba untuk memahami kapan ini mungkin berguna.
Satu skenario bisa jadi seperti ini:
try
{
DatabaseUpdate()
}
catch (SQLException e)
when (driver == "MySQL")
{
//MySQL specific error handling and wrapping up the exception
}
catch (SQLException e)
when (driver == "Oracle")
{
//Oracle specific error handling and wrapping up of exception
}
..
tetapi sekali lagi ini adalah sesuatu yang dapat saya lakukan dalam penangan yang sama dan mendelegasikan ke metode yang berbeda tergantung pada jenis driver. Apakah ini membuat kode lebih mudah dipahami? Bisa dibilang tidak.
Skenario lain yang dapat saya pikirkan adalah seperti:
try
{
SomeOperation();
}
catch(SomeException e)
when (Condition == true)
{
//some specific error handling that this layer can handle
}
catch (Exception e) //catchall
{
throw;
}
Sekali lagi ini adalah sesuatu yang dapat saya lakukan seperti:
try
{
SomeOperation();
}
catch(SomeException e)
{
if (condition == true)
{
//some specific error handling that this layer can handle
}
else
throw;
}
Apakah menggunakan fitur 'catch, when' membuat penanganan exception lebih cepat karena handler dilewati seperti itu dan stack unwinding bisa terjadi jauh lebih awal dibandingkan dengan menangani kasus penggunaan spesifik dalam handler? Adakah kasus penggunaan khusus yang lebih cocok dengan fitur ini yang kemudian dapat diadopsi sebagai praktik yang baik?
sumber
when
kebutuhan untuk mengakses pengecualian itu sendiritry..catch...catch..catch..finally
?catch (Exception ex)
, memeriksa jenis, danthrow
sebaliknya. Kode yang sedikit lebih terorganisir (alias menghindari gangguan kode) adalah alasan mengapa fitur ini ada. (Ini sebenarnya berlaku untuk banyak fitur.)Jawaban:
Catch block sudah memungkinkan Anda untuk memfilter jenis pengecualian:
The
when
klausul memungkinkan Anda untuk memperpanjang filter ini untuk ekspresi generik.Dengan demikian, Anda menggunakan
when
klausa untuk kasus di mana jenis pengecualian tidak cukup berbeda untuk menentukan apakah pengecualian harus ditangani di sini atau tidak.Kasus penggunaan yang umum adalah jenis pengecualian yang sebenarnya merupakan pembungkus untuk beberapa jenis kesalahan yang berbeda.
Inilah kasus yang sebenarnya saya gunakan (di VB, yang sudah memiliki fitur ini untuk beberapa waktu):
Sama untuk
SqlException
, yang juga memilikiErrorCode
properti. Alternatifnya akan seperti itu:yang bisa dibilang kurang elegan dan sedikit merusak stack trace .
Selain itu, Anda dapat menyebutkan jenis pengecualian yang sama dua kali dalam blok coba-tangkap yang sama:
yang tidak akan mungkin terjadi tanpa
when
kondisi tersebut.sumber
catch
, bukan?when
memungkinkan Anda menangani jenis pengecualian yang sama beberapa kali. Anda harus menyebutkannya juga karena ini adalah perbedaan yang sangat penting. Tanpawhen
Anda akan mendapatkan kesalahan kompiler.Dari wiki Roslyn (penekanan milik saya):
Poin pertama patut didemonstrasikan.
Jika kita menjalankan ini di WinDbg hingga pengecualian tercapai, dan mencetak tumpukan menggunakan
!clrstack -i -a
kita akan melihat bingkai dariA
:Namun, jika kita mengubah program untuk menggunakan
when
:Kami akan melihat tumpukan juga berisi
B
bingkai:Informasi tersebut bisa sangat berguna saat men-debug crash dump.
sumber
throw;
(sebagai lawanthrow ex;
) membiarkan tumpukan tidak terluka juga? 1 untuk hal efek samping. Saya tidak yakin saya menyetujuinya, tetapi ada baiknya mengetahui tentang teknik itu.throw;
, tumpukan terlepas dan Anda kehilangan nilai parameter.throw;
mengubah jejak tumpukan sedikit dan banyakthrow ex;
mengubahnya.throw
memang sedikit mengganggu jejak tumpukan. Nomor baris berbeda saat digunakanthrow
sebagai lawanwhen
.Ketika sebuah eksepsi dilemparkan, lintasan pertama penanganan eksepsi mengidentifikasi di mana eksepsi akan ditangkap sebelum melepaskan tumpukan; jika / ketika lokasi "catch" diidentifikasi, semua blok "akhirnya" dijalankan (perhatikan bahwa jika pengecualian lolos dari blok "akhirnya", pemrosesan pengecualian sebelumnya dapat ditinggalkan). Setelah itu terjadi, kode akan melanjutkan eksekusi di "catch".
Jika ada breakpoint dalam fungsi yang dievaluasi sebagai bagian dari "when", breakpoint tersebut akan menangguhkan eksekusi sebelum stack unwinding terjadi; sebaliknya, breakpoint pada "catch" hanya akan menghentikan eksekusi setelah semua
finally
handler berjalan.Akhirnya, jika baris 23 dan 27
foo
panggilanbar
, dan panggilan pada baris 23 melontarkan pengecualian yang tertangkap di dalamfoo
dan ditarik kembali pada baris 57, maka jejak tumpukan akan menyarankan bahwa pengecualian terjadi saat memanggilbar
dari baris 57 [lokasi pelemparan ulang] , menghancurkan informasi apa pun tentang apakah pengecualian terjadi pada panggilan baris-23 atau baris-27. Menggunakanwhen
untuk menghindari menangkap pengecualian di tempat pertama menghindari gangguan seperti itu.BTW, pola berguna yang sangat aneh di C # dan VB.NET adalah menggunakan pemanggilan fungsi dalam
when
klausa untuk menyetel variabel yang dapat digunakan dalamfinally
klausa untuk menentukan apakah fungsi selesai secara normal, untuk menangani kasus di mana suatu fungsi tidak memiliki harapan untuk "menyelesaikan" pengecualian apa pun yang terjadi tetapi harus mengambil tindakan berdasarkan pengecualian tersebut. Misalnya, jika pengecualian dilemparkan dalam metode pabrik yang seharusnya mengembalikan objek yang merangkum sumber daya, sumber daya apa pun yang diperoleh harus dirilis, tetapi pengecualian yang mendasarinya harus meresap ke pemanggil. Cara terbersih untuk menanganinya secara semantik (meskipun tidak secara sintaksis) adalah dengan memiliki filefinally
cekal apakah pengecualian terjadi dan, jika demikian, lepaskan semua sumber daya yang diperoleh atas nama objek yang tidak akan dikembalikan. Karena kode pembersihan tidak memiliki harapan untuk menyelesaikan kondisi apa pun yang menyebabkan pengecualian, seharusnya tidakcatch
demikian, tetapi hanya perlu mengetahui apa yang terjadi. Memanggil fungsi seperti:dalam
when
klausa akan memungkinkan fungsi pabrik untuk mengetahui bahwa sesuatu telah terjadi.sumber