Haruskah Anda mengatur semua objek ke null
( Nothing
dalam VB.NET) setelah Anda selesai dengan mereka?
Saya mengerti bahwa dalam. NET adalah penting untuk membuang contoh objek yang mengimplementasikan IDisposable
antarmuka untuk melepaskan beberapa sumber daya meskipun objek masih bisa menjadi sesuatu setelah dibuang (karena itu isDisposed
properti dalam bentuk), jadi saya menganggapnya masih bisa berada dalam memori atau setidaknya sebagian?
Saya juga tahu bahwa ketika sebuah objek keluar dari ruang lingkup itu kemudian ditandai untuk koleksi siap untuk lulus berikutnya dari pengumpul sampah (meskipun ini mungkin membutuhkan waktu).
Jadi dengan ini dalam pikiran akan mengaturnya untuk null
mempercepat sistem melepaskan memori karena tidak harus bekerja bahwa itu tidak lagi dalam ruang lingkup dan apakah mereka ada efek samping yang buruk?
Artikel MSDN tidak pernah melakukan ini dalam contoh dan saat ini saya melakukan ini karena saya tidak dapat melihat bahayanya. Namun saya telah menemukan campuran pendapat sehingga komentar apa pun berguna.
Jawaban:
Karl benar-benar benar, tidak perlu mengatur objek ke null setelah digunakan. Jika suatu objek mengimplementasikan
IDisposable
, pastikan Anda meneleponIDisposable.Dispose()
ketika Anda selesai dengan objek itu (dibungkus dengantry
..finally
, atau, satuusing()
blok). Tetapi bahkan jika Anda tidak ingat untuk meneleponDispose()
, metode finalis pada objek harus memanggilDispose()
Anda.Saya pikir ini adalah perawatan yang baik:
dan ini
Tidak ada gunanya mencoba menebak GC dan strategi manajemennya yang kedua karena penyesuaian diri dan buram. Ada diskusi yang bagus tentang cara kerja batin dengan Jeffrey Richter di Dot Net Rocks di sini: Jeffrey Richter di Windows Memory Model dan Richters buku CLR via C # bab 20 memiliki perlakuan yang luar biasa:
sumber
Alasan lain untuk menghindari pengaturan objek ke nol ketika Anda selesai dengan mereka adalah bahwa itu benar-benar dapat membuat mereka hidup lebih lama.
misalnya
akan memungkinkan objek yang dirujuk oleh someType menjadi GC setelah panggilan ke "DoSomething" tetapi
terkadang dapat menjaga objek tetap hidup sampai akhir metode. The JIT biasanya akan dioptimalkan pergi tugas ke nol , sehingga kedua bit kode akhir sampai menjadi sama.
sumber
GC.KeepAlive(someType);
Lihat ericlippert.com/2013/06/10/construction-destructionTidak, jangan null objek. Anda dapat memeriksa http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx untuk informasi lebih lanjut, tetapi mengatur berbagai hal to null tidak akan melakukan apa pun, kecuali mengotori kode Anda.
sumber
Juga:
sumber
Secara umum, tidak perlu membatalkan objek setelah digunakan, tetapi dalam beberapa kasus saya menemukan ini adalah praktik yang baik.
Jika suatu objek mengimplementasikan IDisposable dan disimpan dalam bidang, saya pikir itu baik untuk membatalkannya, hanya untuk menghindari menggunakan objek yang dibuang. Bug dari jenis berikut ini bisa menyakitkan:
Ada baiknya untuk membatalkan bidang setelah membuangnya, dan mendapatkan NullPtrEx tepat di baris tempat bidang tersebut digunakan lagi. Jika tidak, Anda mungkin mengalami beberapa bug cryptic di telepon (tergantung pada apa yang DoSomething lakukan).
sumber
.Dispose()
. Jika Anda menemukannya, Anda tidak menggunakan IDisposable dengan benar. Satu-satunya penggunaan untuk objek sekali pakai harus dalam batas blok penggunaan. Dan setelah menggunakan-blok, Anda bahkan tidak memiliki aksesmyField
lagi. Dan di dalam blok menggunakan, pengaturan kenull
tidak diperlukan, blok menggunakan akan membuang objek untuk Anda.Kemungkinannya adalah bahwa kode Anda tidak terstruktur cukup ketat jika Anda merasa perlu untuk
null
variabel.Ada beberapa cara untuk membatasi ruang lingkup variabel:
Seperti yang disebutkan oleh Steve Tranby
Demikian pula, Anda cukup menggunakan kurung keriting:
Saya menemukan bahwa menggunakan kurung keriting tanpa "heading" untuk benar-benar membersihkan kode dan membantu membuatnya lebih dimengerti.
sumber
Satu-satunya waktu Anda harus menetapkan variabel ke nol adalah ketika variabel tidak keluar dari ruang lingkup dan Anda tidak lagi membutuhkan data yang terkait dengannya. Kalau tidak, tidak perlu.
sumber
Secara umum tidak perlu diatur ke nol. Tapi misalkan Anda memiliki fungsi Reset di kelas Anda.
Maka Anda mungkin melakukannya, karena Anda tidak ingin memanggil buang dua kali, karena beberapa dari pembuangan tersebut mungkin tidak diimplementasikan dengan benar dan membuang System.ObjectDosedosed exception.
sumber
jenis "tidak perlu mengatur objek menjadi nol setelah digunakan" tidak sepenuhnya akurat. Ada saatnya Anda perlu NULL variabel setelah membuangnya.
Ya, Anda harus SELALU menelepon
.Dispose()
atau.Close()
pada apa pun yang memilikinya ketika Anda selesai. Baik itu file handle, koneksi basis data atau objek sekali pakai.Terpisah dari itu adalah pola LazyLoad yang sangat praktis.
Katakanlah saya punya dan instantiated
ObjA
ofclass A
.Class A
memiliki properti publik disebutPropB
dariclass B
.Secara internal,
PropB
menggunakan variabel pribadi_B
dan default ke nol. KetikaPropB.Get()
digunakan, memeriksa untuk melihat apakah_PropB
batal jika, membuka sumber daya yang dibutuhkan untuk instantiateB
ke_PropB
. Kemudian kembali_PropB
.Bagi pengalaman saya, ini adalah trik yang sangat berguna.
Dimana kebutuhan untuk null masuk adalah jika Anda mengatur ulang atau mengubah A dalam beberapa cara bahwa isi
_PropB
adalah anak dari nilai-nilai sebelumnyaA
, Anda harus Buang DAN null keluar_PropB
sehingga LazyLoad dapat mengatur ulang untuk mengambil nilai yang tepat JIKA kode membutuhkannya.Jika Anda hanya melakukan
_PropB.Dispose()
dan tak lama setelah mengharapkan pemeriksaan nol untuk LazyLoad berhasil, itu tidak akan nol, dan Anda akan melihat data basi. Akibatnya, Anda harus membatalkannyaDispose()
hanya untuk memastikan.Saya yakin berharap itu sebaliknya, tapi saya punya kode sekarang menunjukkan perilaku ini setelah
Dispose()
pada_PropB
dan di luar fungsi panggilan yang melakukan Buang (dan dengan demikian hampir di luar ruang lingkup), alat peraga pribadi masih tidak nol, dan data basi masih ada.Pada akhirnya, properti yang dibuang akan dibatalkan, tetapi itu tidak menentukan dari sudut pandang saya.
Alasan intinya, seperti yang disinggung dbkk adalah bahwa wadah induk (
ObjA
withPropB
) menjaga instance_PropB
dalam ruang lingkup, meskipunDispose()
.sumber
Ada beberapa kasus di mana masuk akal untuk membatalkan referensi. Misalnya, ketika Anda sedang menulis koleksi - seperti antrian prioritas - dan dengan kontrak Anda, Anda tidak boleh membiarkan benda-benda itu hidup untuk klien setelah klien menghapusnya dari antrian.
Tapi hal semacam ini hanya penting dalam koleksi berumur panjang. Jika antrian tidak akan bertahan pada akhir fungsi yang dibuatnya, maka itu jauh lebih penting.
Secara keseluruhan, Anda benar-benar tidak perlu repot. Biarkan kompiler dan GC melakukan pekerjaan mereka sehingga Anda dapat melakukan pekerjaan Anda.
sumber
Lihatlah artikel ini juga: http://www.codeproject.com/KB/cs/idisposable.aspx
Sebagian besar, mengatur objek ke null tidak berpengaruh. Satu-satunya waktu Anda harus yakin untuk melakukannya adalah jika Anda bekerja dengan "objek besar", yang berukuran lebih besar dari 84K (seperti bitmap).
sumber
Stephen Cleary menjelaskan dengan sangat baik dalam posting ini: Haruskah Saya Mengatur Variabel ke Null untuk Membantu Pengumpulan Sampah?
Kata:
Hal penting yang harus kita pertimbangkan adalah Static Fields .
Kesimpulan:
sumber
Saya percaya dengan desain dari implementor GC, Anda tidak dapat mempercepat GC dengan pembatalan. Saya yakin mereka lebih suka Anda tidak khawatir dengan bagaimana / kapan GC berjalan - perlakukan seperti ini di mana-mana Menjadi melindungi dan mengawasi dan keluar untuk Anda ... (busur menunduk, mengangkat kepalan ke langit) .. .
Secara pribadi, saya sering secara eksplisit mengatur variabel ke nol ketika saya selesai dengan mereka sebagai bentuk dokumentasi diri. Saya tidak mendeklarasikan, menggunakan, lalu mengatur untuk membatalkan nanti - Saya membatalkan segera setelah itu tidak diperlukan lagi. Aku berkata, secara eksplisit, "Aku secara resmi selesai denganmu ... pergi ..."
Apakah pembatalan diperlukan dalam bahasa GC'd? Tidak. Apakah ini bermanfaat untuk GC? Mungkin ya, mungkin tidak, tidak tahu pasti, dengan desain saya benar-benar tidak bisa mengendalikannya, dan terlepas dari jawaban hari ini dengan versi ini atau itu, implementasi GC di masa depan dapat mengubah jawaban di luar kendali saya. Plus jika / ketika nulling dioptimalkan keluar itu sedikit lebih dari komentar mewah jika Anda mau.
Saya membayangkan jika itu membuat niat saya menjadi lebih jelas bagi orang bodoh miskin berikutnya yang mengikuti jejak saya, dan jika itu "mungkin" berpotensi membantu GC kadang-kadang, maka itu sangat berharga bagi saya. Kebanyakan itu membuat saya merasa rapi dan jelas, dan Mongo suka merasa rapi dan jelas. :)
Saya melihatnya seperti ini: Bahasa pemrograman ada untuk memungkinkan orang memberi ide kepada orang lain dan kompiler permintaan pekerjaan tentang apa yang harus dilakukan - kompiler mengonversi permintaan itu menjadi bahasa yang berbeda (kadang-kadang beberapa) untuk CPU - CPU dapat memberikan hoot bahasa apa yang Anda gunakan, pengaturan tab Anda, komentar, penekanan gaya, nama variabel, dll. - CPU adalah semua tentang bit stream yang memberi tahu apa yang register dan opcode dan lokasi memori untuk bermain-main. Banyak hal yang ditulis dalam kode tidak dikonversi menjadi apa yang dikonsumsi oleh CPU dalam urutan yang kami tentukan. C, C ++, C #, Lisp, Babel, assembler atau apa pun kita adalah teori daripada kenyataan, ditulis sebagai pernyataan kerja. Apa yang Anda lihat bukan apa yang Anda dapatkan, ya, bahkan dalam bahasa assembler.
Saya mengerti pola pikir "hal-hal yang tidak perlu" (seperti garis kosong) "tidak lain hanyalah derau dan kekacauan kode." Itu adalah awal karier saya; Saya benar-benar mengerti. Pada titik ini saya condong ke arah yang membuat kode lebih jelas. Ini tidak seperti saya menambahkan bahkan 50 baris "noise" ke program saya - itu beberapa baris di sini atau di sana.
Ada pengecualian untuk aturan apa pun. Dalam skenario dengan memori yang mudah menguap, memori statis, kondisi balapan, lajang, penggunaan data "basi" dan semua jenis busuk itu, itu berbeda: Anda PERLU mengelola memori Anda sendiri, mengunci dan membatalkan sebagai apropos karena memori bukan bagian dari GC'd Universe - semoga semua orang mengerti itu. Sisa waktu dengan bahasa GC'd itu masalah gaya daripada kebutuhan atau peningkatan kinerja yang dijamin.
Pada akhirnya, pastikan Anda memahami apa yang memenuhi syarat untuk GC dan apa yang tidak; mengunci, membuang, dan membatalkan dengan tepat; lilin menyala, lilin mati; bernafas, bernafas; dan untuk semua yang lain saya katakan: Jika rasanya enak, lakukanlah. Jarak tempuh Anda mungkin bervariasi ... sebagaimana mestinya ...
sumber
Saya pikir pengaturan sesuatu kembali ke nol berantakan. Bayangkan sebuah skenario di mana item yang diatur untuk sekarang diekspos katakanlah melalui properti. Sekarang entah bagaimana beberapa kode secara tidak sengaja menggunakan properti ini setelah item dibuang, Anda akan mendapatkan pengecualian referensi nol yang memerlukan beberapa penyelidikan untuk mencari tahu apa yang sebenarnya terjadi.
Saya percaya kerangka kerja sekali pakai akan memungkinkan membuang ObjectDisposedException yang lebih bermakna. Tidak mengatur ini kembali ke nol akan lebih baik daripada itu untuk alasan itu.
sumber
Beberapa objek mengira
.dispose()
metode yang memaksa sumber daya untuk dihapus dari memori.sumber