Untuk tipikal yang if...else
dibungkus dengan penanganan pengecualian, apakah contoh berikut ini merupakan praktik yang disarankan untuk menghindari duplikasi kode?
try
{
if (GetDataFromServer())
{
return ProcessData();
}
else
{
throw new Exception();
}
catch(Exception ex)
{
return null;
}
dari pada...
try
{
if (GetDataFromServer())
{
return ProcessData();
}
else
{
return null;
}
}
catch(Exception ex)
{
return null;
}
Saya tahu ada sedikit peningkatan kinerja, tapi saya bertanya-tanya apakah ini dianggap sebagai praktik yang dapat diterima. Saat ini saya melakukannya dengan metode kedua - terutama dalam kasus di mana saya perlu menangani pengecualian khusus secara berbeda - tetapi saya bertanya-tanya apakah metode pertama sesuai untuk kasus-kasus sederhana.
c#
exception-handling
grovesNL
sumber
sumber
Jawaban:
Menggunakan penanganan pengecualian untuk kontrol aliran tidak disarankan oleh Microsoft.
Dan meja bundar tentang topik tersedia.
Yang sedang berkata, C # mendukung melakukannya, dan saya kira itu tergantung pada kondisi yang dihadapi apakah pengecualian adalah respon yang paling tepat.
sumber
Hit kinerja paling mungkin diabaikan, seperti dijelaskan dalam jawaban ini .
Jadi mari kita pergi dengan gagasan bahwa kinerja bukan masalah. Anda melempar
System.Exception
, hanya untuk memindahkan eksekusi kecatch
klausa . Melempar aBadControlFlowThatShouldBeRewrittenException
mungkin akan berlebihan.Mari kita hancurkan ini. Kita punya:
GetDataFromServer
(nama metode harus PascalCase dalam C #), yang mungkin dapat melempar pengecualian, atau mengembalikan abool
.true
, jalankanProcessData
.null
sebaliknya.Sepertinya metode di mana kode ini ditulis, hanya melakukan terlalu banyak hal.
GetDataFromServer
mengembalikanbool
tampilan seperti cacat desain, saya akan mengharapkan metode untuk mengembalikan data yang didapatnya dari server , beberapaIEnumerable<SomeType>
yang akan berisi 0 atau lebih item - yaitu jalur bahagia mengembalikan n item di mana n> 0 , tidak begitu bahagia path mengembalikan 0 item, dan path yang tidak bahagia meledak dengan pengecualian yang tidak tertangani, apa pun itu.Itu mengubah seperti apa metodenya, cukup banyak - sekali lagi sulit untuk mengatakan apakah ini masuk akal, karena posting asli hanya memiliki satu titik keluar (dan dengan demikian tidak dapat dikompilasi, karena tidak semua jalur kode mengembalikan nilai ), jadi ini hanya tebakan liar:
Di sini Anda akan melihat
ProcessData
dan melihat bahwa iterasiresult
, dan kembalinull
jika tidak ada item diIEnumerable
.Sekarang mengapa metodenya kembali
null
? Server sedang down? Apakah ada bug dalam kueri? String koneksi menggunakan kredensial yang salah? Setiap kaliGetDataFromServer
meledak dengan pengecualian yang tidak Anda harapkan, Anda menelannya, mendorongnya di bawah karpet dan mengembalikannull
nilai. Saya akan merekomendasikan menangkap pengecualian khusus dalam kasus ini, dan mencatat semuanya; debugging akan jauh lebih mudah seperti itu.Dengan
catch
klausa umum yang tidak menangkap pengecualian, akan sangat sulit untuk mendiagnosis apa pun. Saya akan melakukan ini secara minimal:Sekarang Anda setidaknya bisa istirahat dan memeriksa
e
jika ada masalah.TL; DR : Tidak, melempar dan menangkap pengecualian untuk kontrol aliran bukanlah ide yang baik.
sumber
dalam jawaban pertama Anda ada hit kinerja yang tidak perlu ada di sana.
ketika Anda keluar dari pernyataan if untuk masuk ke pernyataan Catch ketika Anda tidak harus membuat arah pengalihan kode, bisa dikatakan.
jika Anda ingin
return null;
melakukannya dalam pernyataan lain tidak dalam tangkapan yang ditangkap setelah dilemparkan dari pernyataan lain.Mungkin tidak berlaku untuk Anda Estat kode, tapi untuk kode Generik yang Anda berikan itu tidak berlaku.
Standar mengatakan Anda tidak boleh melakukan ini.
Standar mengatakan Anda harus melakukannya seperti ini, (sekali lagi berdasarkan pada Kode Generik yang Diberikan dalam OP)
dan karena Anda tidak memiliki pengecualian khusus yang Anda tangkap, Anda bahkan tidak boleh mencoba menangkapnya di sini.
Anda ingin melihat Pengecualian saat itu terjadi sehingga Anda dapat memperbaiki masalah yang menciptakan pengecualian.
sumber
Kenapa tidak jauh lebih sederhana:
Jika eksepsi handler akan ada, seharusnya di ProcessData ()
sumber
ProcessData()
ke tingkat paling atas?ProcessData()
melempar pengecualian sekarang tidak ditangani. Saya inginreturn null
di level ini jikaProcessData()
melempar pengecualian, tanpa memodifikasiProcessData()
sendiri.