Apakah praktik yang buruk untuk kembali dari dalam percobaan menangkap akhirnya menghalangi?

128

Jadi saya menemukan beberapa kode pagi ini yang terlihat seperti ini:

try
{
    x = SomeThingDangerous();
    return x;
}
catch (Exception ex)
{
    throw new DangerousException(ex);
}
finally
{
    CleanUpDangerousStuff();
}

Sekarang kode ini mengkompilasi dengan baik dan berfungsi sebagaimana mestinya, tetapi rasanya tidak tepat untuk kembali dari dalam blok coba, terutama jika akhirnya ada yang terkait.

Masalah utama saya adalah apa yang terjadi jika akhirnya melemparkan pengecualian itu sendiri? Anda mendapatkan variabel yang dikembalikan tetapi juga pengecualian untuk ditangani ... jadi saya tertarik untuk mengetahui pendapat orang lain tentang kembali dari dalam blok percobaan?

lomaxx
sumber
13
Salah satu manfaat gaya ini adalah Anda tidak perlu mendeklarasikan di xluar tryblok. Anda dapat menjaga deklarasi dekat dengan penggunaannya.
David R Tribble

Jawaban:

169

Tidak, ini bukan praktik buruk. Menempatkan di returntempat yang masuk akal meningkatkan keterbacaan dan pemeliharaan dan membuat kode Anda lebih mudah dimengerti. Anda seharusnya tidak peduli karena finallyblok akan dieksekusi jika ada returnpernyataan.

Mehrdad Afshari
sumber
19

Akhirnya akan dieksekusi tidak peduli apa, jadi tidak masalah.

Ed S.
sumber
9
Tidak, pada kenyataannya, ini bukan hanya memasukkan, ada beberapa pengecualian yang disebut pengecualian async seperti StackOverflowException, ThreadAbortException dan OutOfMemoryException yang mungkin menyebabkan blok akhirnya tidak dieksekusi. Baca tentang wilayah eksekusi terbatas untuk menangani skenario ini.
Mehrdad Afshari
Tautan ini menjelaskannya: kembalikan Pernyataan dan coba ... tangkap ... akhirnya Pernyataan
amit jha
14

Secara pribadi, saya akan menghindari pengkodean seperti ini karena saya tidak ingin melihat pernyataan pengembalian sebelum akhirnya pernyataan.

Pikiranku sederhana dan prosesnya agak linier. Oleh karena itu ketika saya berjalan melalui kode untuk lari kering, saya akan cenderung berpikir bahwa begitu saya dapat mencapai pernyataan kembali, semuanya mengikuti tidak masalah yang jelas sangat salah dalam kasus ini (bukan bahwa itu akan mempengaruhi pernyataan kembali tetapi apa efek sampingnya).

Jadi, saya akan mengatur kode sehingga pernyataan kembali selalu muncul setelah pernyataan terakhir.

Conrad
sumber
9

Ini mungkin menjawab pertanyaan Anda

Apa yang sebenarnya terjadi dalam percobaan {return x; } akhirnya {x = null; } pernyataan?

Dari membaca pertanyaan itu, sepertinya Anda dapat memiliki struktur coba tangkap lagi dalam pernyataan terakhir jika Anda berpikir itu bisa menimbulkan pengecualian. Kompiler akan mencari tahu kapan harus mengembalikan nilai.

Yang mengatakan, mungkin lebih baik untuk merestrukturisasi kode Anda supaya tidak membingungkan Anda nanti atau orang lain yang mungkin tidak menyadari hal ini juga.

Spencer Ruport
sumber
hmmm sangat menarik. Jadi itu berarti aman, tetapi apakah itu berarti harus dihindari?
lomaxx
3
Secara pribadi saya pikir itu membuat keterbacaan kode Anda sedikit sulit dan itu saja sudah cukup untuk membuat saya mencari cara lain untuk menyusun kode. Tapi sebenarnya itu hanya preferensi pribadi.
Spencer Ruport
3
Saya cenderung setuju dengan preferensi pribadi Anda :)
lomaxx
Saya pikir pengembaliannya baik-baik saja. Metode akan mengembalikan nilai, kecuali jika ada pengecualian; tidak masalah jika pengecualian muncul pada kode pembersihan akhirnya.
Lawrence Dol
Perhatikan bahwa batasan untuk kembali dari akhirnya tidak ada di Jawa (tapi saya pikir batasannya bagus - pujian untuk C #).
Lawrence Dol
5

Secara fungsional tidak ada perbedaan.

Namun ada satu alasan untuk tidak melakukan ini. Metode yang lebih panjang dengan beberapa titik keluar seringkali lebih sulit untuk dibaca dan dianalisis. Tapi keberatan itu lebih banyak berkaitan dengan pernyataan pengembalian daripada tangkapan dan akhirnya diblokir.

Ifeanyi Echeruo
sumber
Saya akan menantang ini karena Anda bisa berakhir dengan lebih banyak sarang yang juga membuat lebih sulit untuk membaca kompleksitas siklomatik yang lebih tinggi
matt_lethargic
3

Dalam contoh Anda, kedua cara itu setara, saya bahkan tidak akan terkejut jika kompiler menghasilkan kode yang sama. Jika pengecualian terjadi di blok akhirnya Anda memiliki masalah yang sama apakah Anda meletakkan pernyataan kembali di blok atau di luarnya.

Pertanyaan sebenarnya adalah gaya yang terbaik. Saya suka menulis metode saya sehingga hanya ada satu pernyataan kembali, dengan cara ini lebih mudah untuk melihat aliran keluar dari metode, maka saya juga suka menempatkan pernyataan kembali terakhir sehingga mudah untuk melihat bahwa itu adalah akhir metode dan ini apa yang dikembalikan.

Saya pikir dengan pernyataan pengembalian sangat rapi ditempatkan sebagai pernyataan terakhir, orang lain cenderung datang dan memercikkan banyak pernyataan pengembalian ke bagian lain dari metode ini.

BeWarned
sumber