Saya hanya ingin tahu apakah itu pendekatan yang aman / baik untuk menelepon ke return
dalam using
blok.
Misalnya.
using(var scope = new TransactionScope())
{
// my core logic
return true; // if condition met else
return false;
scope.Complete();
}
Kami tahu bahwa penjepit paling keriting terakhir dispose()
akan dibatalkan. Tapi apa yang akan terjadi dalam kasus di atas, karena return
melompati kontrol dari cakupan yang diberikan (AFAIK) ...
- Apakah saya
scope.Complete()
dipanggil? - Dan untuk metode ruang lingkup
dispose()
.
using{}
ruang lingkup selesai, objek yang relevan dibuang,return
akan "merusak" ruang lingkup - sehingga benda akan dibuang seperti yang diharapkanscope.Complete()
panggilan Anda tidak akan pernah dipukul dengan sampel yang Anda berikan, jadi transaksi Anda akan selalu dibatalkan.using
'sdispose()
disebut, ketika Anda kembali, fungsi mengandung iniusing
blok akan telah kembali dan semuanya milik itu akan menjadi yatim piatu. Jadi bahkan jikascope
tidak dibuang "olehusing
" (itu akan, seperti yang dijelaskan orang lain) itu akan tetap dibuang karena fungsinya berakhir. Jika C # memilikigoto
pernyataan -Apakah Anda sudah selesai tertawa? baik- maka alih-alih kembali Anda bisagoto
setelah penjepit penutup, tanpa kembali. Logikanya,scope
mau tetap dibuang, tapi Anda baru saja memasukkangoto
C # jadi siapa yang peduli dengan logika pada tahap itu.Jawaban:
Sangat aman untuk menelepon ke
return
dalamusing
blok Anda , karena blok yang menggunakan hanyalah sebuahtry/finally
blok.Dalam contoh Anda di atas setelah pengembalian
true
, ruang lingkup akan dibuang dan nilainya dikembalikan.return false
, dan tidakscope.Complete()
akan dipanggil. Namun akan dipanggil karena itu berada di dalam blok terakhir.Dispose
Kode Anda pada dasarnya sama dengan ini (jika itu membuatnya lebih mudah untuk dipahami):
var scope = new TransactionScope()) try { // my core logic return true; // if condition met else return false; scope.Complete(); } finally { if( scope != null) ((IDisposable)scope).Dispose(); }
Perlu diketahui bahwa transaksi Anda tidak akan pernah berhasil karena tidak ada cara
scope.Complete()
untuk melakukan transaksi tersebut.sumber
Dispose
akan dipanggil. Jika OP tidak tahu apa yang terjadiusing
, kemungkinan besar dia tidak tahu apa yang terjadifinally
.using
, misalnyausing (var callersVar = MyFunc(..)) ..
, alih - alih menggunakan di dalam "MyFunc" - Maksud saya, penelepon diberi aliran dan bertanggung jawab untuk menutupnya melaluiusing
atau secara eksplisit, atau (b) minta MyFunc mengekstrak info apa pun yang diperlukan ke objek lain, yang dapat diteruskan kembali dengan aman - maka objek atau aliran data yang mendasarinya dapat dibuang oleh Andausing
. Anda tidak perlu menulis kode bocor.Tidak apa-apa -
finally
klausa (yang dilakukan oleh kurung kurawal penutupusing
klausa di bawah kap) selalu dijalankan saat ruang lingkup ditinggalkan, tidak peduli bagaimana caranya.Namun, ini hanya berlaku untuk pernyataan yang ada di blok akhirnya (yang tidak dapat diatur secara eksplisit saat menggunakan
using
). Oleh karena itu, dalam contoh Anda,scope.Complete()
tidak akan pernah dipanggil (saya berharap kompilator memperingatkan Anda tentang kode yang tidak dapat dijangkau).sumber
Secara umum, ini adalah pendekatan yang bagus. Namun dalam kasus Anda, jika Anda kembali sebelum memanggil
scope.Complete()
, itu hanya akan membuang TransactionScope. Tergantung desain Anda.Jadi, dalam contoh ini, Complete () tidak dipanggil, dan cakupan dibuang, dengan anggapan itu mewarisi antarmuka IDisposable.
sumber
scope.Complete pasti harus dipanggil sebelumnya
return
. Compiler akan menampilkan peringatan dan kode ini tidak akan pernah dipanggil.Mengenai
return
dirinya sendiri - ya, aman untuk menyebutnyausing
pernyataan dalam . Menggunakan diterjemahkan untuk mencoba-akhirnya memblokir di belakang layar dan akhirnya memblokir harus dieksekusi.sumber
Dalam contoh yang Anda berikan, ada masalah;
scope.Complete()
tidak pernah dipanggil. Kedua, bukanlah praktik yang baik untuk menggunakanreturn
pernyataan di dalamusing
pernyataan. Lihat berikut ini:using(var scope = new TransactionScope()) { //have some logic here return scope; }
Dalam contoh sederhana ini, intinya adalah; nilai
scope
akan menjadi null saat menggunakan pernyataan selesai.Jadi lebih baik tidak kembali ke dalam menggunakan pernyataan.
sumber
scope
tidak akan null - satu-satunya hal yang akan terjadi adalah bahwaDispose()
akan telah dipanggil pada contoh itu, dan karena itu contoh harus tidak digunakan lagi (tetapi tidak batal dan tidak ada yang mencegah Anda untuk mencoba dan menggunakan objek yang dibuang, meskipun ini memang penggunaan yang tidak tepat dari objek sekali pakai).return scope
mengembalikan referensi ke yang objek. Dengan cara ini, jika Anda menetapkan referensi itu saat kembali, Anda mencegah GC membersihkan objek yang dibuang.Untuk memastikan bahwa
scope.Complete()
akan dipanggil, bungkus dengantry/finally
. Thedispose
disebut karena Anda harus membungkusnya denganusing
yang alternatiftry/finally
blok.using(var scope = new TransactionScope()) { try { // my core logic return true; // if condition met else return false; } finally { scope.Complete(); } }
sumber
Dalam contoh ini, scope.Complete () tidak akan pernah dijalankan. Namun, perintah return akan membersihkan semua yang ditugaskan di tumpukan. GC akan menangani semua yang tidak direferensikan. Jadi, kecuali ada objek yang tidak bisa diambil oleh GC, tidak ada masalah.
sumber