Saya baru-baru ini mulai pemrograman di Ruby, dan saya melihat penanganan pengecualian.
Saya bertanya-tanya apakah ensure
Ruby sama dengan finally
di C #? Haruskah saya memiliki:
file = File.open("myFile.txt", "w")
begin
file << "#{content} \n"
rescue
#handle the error here
ensure
file.close unless file.nil?
end
atau haruskah saya melakukan ini?
#store the file
file = File.open("myFile.txt", "w")
begin
file << "#{content} \n"
file.close
rescue
#handle the error here
ensure
file.close unless file.nil?
end
Apakah ensure
dipanggil tidak peduli apa, bahkan jika pengecualian tidak diajukan?
ruby-on-rails
ruby
exception
exception-handling
error-handling
Lloyd Powell
sumber
sumber
begin
blok.Jawaban:
Ya,
ensure
memastikan bahwa kode selalu dievaluasi. Itu sebabnya disebutensure
. Jadi, itu setara dengan Java dan C #finally
.Aliran umum dari
begin
/rescue
/else
/ensure
/end
terlihat seperti ini:Anda bisa keluar
rescue
,ensure
atauelse
. Anda juga dapat mengabaikan variabel dalam hal ini Anda tidak akan dapat memeriksa pengecualian dalam kode penanganan pengecualian Anda. (Ya, Anda selalu dapat menggunakan variabel pengecualian global untuk mengakses pengecualian terakhir yang dimunculkan, tapi itu sedikit gila.) Dan Anda dapat meninggalkan kelas pengecualian, dalam hal ini semua pengecualian yang mewarisi dariStandardError
akan ditangkap. (Harap dicatat bahwa ini tidak berarti bahwa semua pengecualian tertangkap, karena ada pengecualian yang contohException
tapi tidakStandardError
. Pengecualian Kebanyakan sangat parah bahwa kompromi integritas program sepertiSystemStackError
,NoMemoryError
,SecurityError
,NotImplementedError
,LoadError
,SyntaxError
,ScriptError
,Interrupt
,SignalException
atauSystemExit
.)Beberapa blok membentuk blok pengecualian implisit. Sebagai contoh, definisi metode secara implisit juga merupakan blok pengecualian, jadi alih-alih menulis
Anda hanya menulis
atau
Hal yang sama berlaku untuk
class
definisi danmodule
definisi.Namun, dalam kasus spesifik yang Anda tanyakan, sebenarnya ada ungkapan yang jauh lebih baik. Secara umum, ketika Anda bekerja dengan beberapa sumber daya yang Anda perlu bersihkan pada akhirnya, Anda melakukannya dengan melewati blok ke metode yang melakukan semua pembersihan untuk Anda. Ini mirip dengan
using
blok di C #, kecuali bahwa Ruby sebenarnya cukup kuat sehingga Anda tidak perlu menunggu imam besar Microsoft turun dari gunung dan dengan ramah mengubah kompiler mereka untuk Anda. Di Ruby, Anda bisa menerapkannya sendiri:Dan apa yang Anda ketahui: ini sudah tersedia di perpustakaan inti sebagai
File.open
. Tetapi ini adalah pola umum yang dapat Anda gunakan dalam kode Anda sendiri, untuk menerapkan segala jenis pembersihan sumber daya (à lausing
dalam C #) atau transaksi atau apa pun yang mungkin Anda pikirkan.Satu-satunya kasus di mana ini tidak berhasil, jika memperoleh dan melepaskan sumber daya didistribusikan di berbagai bagian program. Tetapi jika dilokalkan, seperti dalam contoh Anda, maka Anda dapat dengan mudah menggunakan blok sumber daya ini.
BTW: di C # modern,
using
sebenarnya berlebihan, karena Anda dapat mengimplementasikan blok sumber daya gaya-Ruby sendiri:sumber
ensure
pernyataan dieksekusi terakhir, itu bukan nilai balik.ensure
dipanggil apa pun yang terjadi."FYI, bahkan jika pengecualian kembali pada
rescue
bagian,ensure
blok akan dieksekusi sebelum eksekusi kode berlanjut ke pengendali pengecualian berikutnya. Contohnya:sumber
Jika Anda ingin memastikan file ditutup, Anda harus menggunakan bentuk blok
File.open
:sumber
Ya,
ensure
dipanggil dalam keadaan apa pun. Untuk informasi lebih lanjut, lihat " Pengecualian, Tangkapan, dan Lempar " buku Ruby Pemrograman dan cari "pastikan".sumber
Ya,
ensure
MEMASTIKAN dijalankan setiap waktu, jadi Anda tidak perlufile.close
dibegin
blok.Omong-omong, cara yang baik untuk menguji adalah dengan melakukan:
Anda dapat menguji untuk melihat apakah "========= di dalam blok pastikan" akan dicetak ketika ada pengecualian. Kemudian Anda dapat mengomentari pernyataan yang memunculkan kesalahan dan melihat apakah
ensure
pernyataan itu dijalankan dengan melihat apakah ada yang dicetak.sumber
Inilah mengapa kita perlu
ensure
:sumber
Ya,
ensure
sepertifinally
jaminan bahwa blok akan dieksekusi . Ini sangat berguna untuk memastikan bahwa sumber daya kritis dilindungi misalnya menutup file menangani kesalahan, atau melepaskan mutex.sumber
File.open
bagian BUKAN di dalam blok begin-pastikan. Hanyafile.close
tetapi tidak cukup.