Anda harus mengatur semua benda untuk null
(apa-Apa
di VB.NET) setelah anda selesai dengan mereka?
Saya memahami bahwa dalam .NET adalah penting untuk membuang setiap contoh benda-benda yang melaksanakan IDisposable
antarmuka untuk melepaskan beberapa sumber walaupun objek masih dapat menjadi sesuatu setelah itu dibuang (maka isDisposed
properti di bentuk), jadi saya berasumsi itu masih berada di dalam memori atau setidaknya sebagian?
Saya juga tahu bahwa ketika sebuah benda keluar dari lingkup itu kemudian ditandai untuk koleksi siap untuk lulus berikutnya dari garbage collector (meskipun ini mungkin memakan waktu).
Jadi dengan ini dalam pikiran akan pengaturan untuk null
mempercepat sistem melepaskan memori karena tidak harus bekerja keluar bahwa itu adalah tidak lagi dalam lingkup dan mereka efek samping yang buruk?
MSDN artikel yang pernah melakukan hal ini dalam contoh-contoh dan saat ini aku melakukan ini karena aku tidak bisa melihat bahaya. Namun saya telah menemukan campuran pendapat sehingga setiap komentar yang berguna.
Karl adalah benar-benar benar, ada tidak perlu untuk mengatur benda-benda ke null setelah digunakan. Jika sebuah objek mengimplementasikan IDisposable
, pastikan anda menelepon IDisposable.Dispose()
ketika anda're dilakukan dengan objek tersebut (yang dibungkus dalam coba-coba
..akhirnya
, atau, menggunakan()
block). Tetapi bahkan jika anda don't lupa untuk memanggil Dispose()
, yang finaliser metode pada objek harus memanggil Dispose()
untuk anda.
Saya pikir ini adalah pengobatan yang baik:
dan ini
Ada isn't ada gunanya mencoba untuk menebak kedua GC dan strategi manajemen karena itu's self tuning dan buram. Ada diskusi yang baik tentang inner dengan Jeffrey Richter pada Dot Net Rocks di sini: Jeffrey Richter pada Jendela Model Memori dan Richters buku CLR melalui C# bab 20 memiliki pengobatan:
Alasan lain untuk menghindari pengaturan objek null ketika anda selesai dengan mereka adalah bahwa hal itu benar-benar dapat membuat mereka hidup lebih lama.
misalnya
void foo()
{
var someType = new SomeType();
someType.DoSomething();
// someType is now eligible for garbage collection
// ... rest of method not using 'someType' ...
}
akan memungkinkan objek yang dirujuk oleh beberapa jenis untuk GC'd setelah panggilan untuk "melakukan sesuatu yang" tapi
void foo()
{
var someType = new SomeType();
someType.DoSomething();
// someType is NOT eligible for garbage collection yet
// because that variable is used at the end of the method
// ... rest of method not using 'someType' ...
someType = null;
}
mungkin kadang-kadang menjaga objek tetap hidup sampai akhir dari metode ini. The JIT biasanya akan dioptimalkan pergi tugas ke null, sehingga kedua potongan kode yang berakhir menjadi sama.
Ada don't null benda-benda. 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 pengaturan hal-hal null won't melakukan apa-apa, kecuali kotor kode anda.
Secara umum, ada's tidak perlu null benda setelah digunakan, tetapi dalam beberapa kasus, saya menemukan itu's praktik yang baik.
Jika sebuah objek mengimplementasikan IDisposable dan disimpan di lapangan, saya pikir itu's baik untuk null, hanya untuk menghindari menggunakan objek dibuang. Bug semacam berikut dapat menyakitkan:
this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();
It's baik untuk null lapangan setelah membuang itu, dan mendapatkan NullPtrEx kanan di baris mana lapangan digunakan lagi. Jika tidak, anda mungkin mengalami beberapa samar bug down the line (tergantung pada apa melakukan sesuatu yang tidak).
Kemungkinannya adalah bahwa kode anda tidak terstruktur cukup erat jika anda merasa perlu untuk null
variabel.
Ada sejumlah cara untuk membatasi ruang lingkup variabel:
Seperti yang disebutkan oleh Steve Tranby
using(SomeObject object = new SomeObject())
{
// do stuff with the object
}
// the object will be disposed of
Demikian pula, anda hanya dapat menggunakan tanda kurung kurawal:
{
// Declare the variable and use it
SomeObject object = new SomeObject()
}
// The variable is no longer available
Saya menemukan bahwa menggunakan kurung kurawal tanpa "judul" untuk benar-benar membersihkan kode dan membantu membuatnya lebih mudah dimengerti.
Pada umumnya tidak perlu set ke null. Tapi misalkan anda memiliki Ulang fungsi di kelas anda.
Kemudian mungkin anda lakukan, karena anda tidak ingin untuk memanggil membuang dua kali, sejak beberapa Membuang tidak dapat dilaksanakan dengan benar dan membuang Sistem.ObjectDisposed terkecuali.
private void Reset()
{
if(_dataset != null)
{
_dataset.Dispose();
_dataset = null;
}
//..More such member variables like oracle connection etc. _oraConnection
}
ini semacam "tidak perlu untuk mengatur benda-benda ke null setelah menggunakan" ini tidak sepenuhnya akurat. Ada saat-saat anda perlu NULL variabel setelah membuang itu.
Ya, anda harus SELALU panggilan .Dispose()
atau .Close()
pada apa pun yang memiliki hal itu ketika anda selesai. Dapat menangani file, koneksi database atau benda-benda pakai.
Terpisah dari itu adalah sangat praktis pola LazyLoad.
Mengatakan saya memiliki dan diturunkan ObjA
dari kelas
. Kelas A
memiliki fasilitas umum yang disebut PropB
dari kelas B
.
Secara internal, PropB
menggunakan variabel pribadi dari _B
dan default null. Ketika PropB.Get()
yang digunakan, memeriksa untuk melihat jika _PropB
adalah nol dan jika itu adalah, membuka sumber daya yang dibutuhkan untuk instantiate B
menjadi _PropB
. Kemudian kembali _PropB
.
Untuk pengalaman saya, ini benar-benar berguna trik.
Di mana perlu null datang adalah jika anda me-reset atau mengubah dalam beberapa cara bahwa isi dari _PropB
adalah anak dari sebelumnya nilai-nilai dari A
, anda akan perlu untuk Membuang DAN batal keluar _PropB
jadi LazyLoad dapat me-reset untuk mengambil nilai yang tepat JIKA kode yang memerlukan.
Jika anda hanya melakukan _PropB.Dispose()
dan tak lama setelah mengharapkan null memeriksa LazyLoad untuk berhasil, itu tidak't menjadi nol, dan anda'akan melihat data basi. Pada dasarnya, anda harus batal setelah Dispose()
hanya untuk memastikan.
Saya yakin berharap yang sebaliknya, tapi saya've punya kode sekarang menunjukkan perilaku ini setelah Dispose()
pada _PropB
dan di luar memanggil fungsi yang melakukan Dispose (dan dengan demikian hampir keluar dari lingkup), swasta prop masih isn't null, dan data basi masih ada.
Akhirnya, dibuang properti akan null keluar, tapi yang's telah non-deterministik dari perspektif saya.
Inti alasan, seperti dbkk menyinggung bahwa wadah induk (ObjA
dengan PropB
) adalah menjaga contoh _PropB
dalam lingkup, meskipun Dispose()
.
Stephen Cleary menjelaskan dengan sangat baik di posting ini: aku Harus Mengatur variabel-Variabel yang Null untuk Membantu Pengumpulan Sampah?
Kata:
Jawaban Singkat, bagi yang tidak Sabar Ya, jika variabel statis lapangan, atau jika anda menulis sebuah enumerable metode (menggunakan yield return) atau asynchronous metode (menggunakan async dan menunggu). Jika tidak, tidak ada.
Ini berarti bahwa dalam metode biasa (non-enumerable dan non-asynchronous), anda tidak menetapkan lokal variabel, parameter metode, atau contoh bidang ke null.
(Bahkan jika anda menerapkan IDisposable.Membuang, anda masih tidak harus mengatur variabel null).
Hal penting yang harus kita pertimbangkan adalah Statis Bidang.
Statis bidang selalu akar benda, sehingga mereka selalu dianggap "hidup" oleh garbage collector. Jika statis bidang referensi objek yang sudah tidak diperlukan lagi, itu harus diatur untuk null sehingga garbage collector akan memperlakukannya sebagai syarat untuk koleksi.
Pengaturan statis bidang null berarti jika seluruh proses adalah mematikan. Seluruh tumpukan akan menjadi sampah yang dikumpulkan pada saat itu, termasuk semua akar benda-benda.
Kesimpulan:
Statis bidang; itu tentang hal itu. Hal lain adalah buang-buang waktu.
Lihat artikel ini juga: http://www.codeproject.com/KB/cs/idisposable.aspx
Untuk sebagian besar, pengaturan objek null tidak memiliki efek. Satu-satunya waktu anda harus yakin untuk melakukannya adalah jika anda bekerja dengan "objek besar", yang satu lebih besar dari 84K dalam ukuran (seperti bitmap).
Ada beberapa kasus di mana masuk akal untuk null referensi. Misalnya, bila anda're tulisan koleksi-seperti antrian prioritas--dan dengan kontrak anda, anda seharusnya't dapat menjaga benda-benda hidup untuk klien setelah klien telah dihapus dari antrian.
Tetapi hal semacam ini hanya hal-hal yang lama tinggal di koleksi. Jika antrian's tidak akan bertahan hidup akhir dari fungsi itu dibuat, maka hal-hal yang jauh lebih sedikit.
Secara keseluruhan, anda benar-benar tidak't repot-repot. Mari compiler dan GC melakukan pekerjaan mereka sehingga anda dapat melakukan milikmu.
Saya pikir pengaturan sesuatu kembali ke null berantakan. Bayangkan sebuah skenario di mana item yang ditetapkan untuk sekarang terkena mengatakan melalui properti. Sekarang adalah entah bagaimana beberapa bagian dari kode yang tidak sengaja menggunakan properti ini setelah item tersebut dibuang anda akan mendapatkan referensi pengecualian yang membutuhkan beberapa penyelidikan untuk mencari tahu persis apa yang terjadi.
Saya percaya kerangka sekali pakai akan memungkinkan membuang ObjectDisposedException yang lebih bermakna. Tidak pengaturan ini kembali ke nol akan menjadi lebih baik maka untuk alasan itu.
Saya percaya dengan desain GC pelaksana, anda dapat't mempercepat GC dengan pembatalan. I'm yakin mereka'd sukai anda tidak khawatir dengan bagaimana/kapan GC berjalan -- memperlakukannya seperti ini di mana-mana Menjadi melindungi dan mengawasi keluar untuk anda...(busur kepala di bawah, mengangkat kepalan tangan ke langit)...
Secara pribadi, saya sering secara eksplisit menetapkan variabel dengan nol ketika saya'm dilakukan dengan mereka sebagai bentuk dokumentasi. Saya don't menyatakan, penggunaan, kemudian set ke null kemudian-aku null segera setelah mereka're tidak lagi diperlukan. I'm mengatakan, secara eksplisit, "aku'm secara resmi dilakukan dengan kau...pergi..."
Adalah meniadakan diperlukan dalam GC'd bahasa? No. Apakah itu membantu untuk GC? Mungkin ya, mungkin tidak, don't tahu pasti, dengan desain yang benar-benar saya dapat't control, dan terlepas dari hari ini's jawaban dengan versi ini atau itu, masa depan GC implementasi bisa mengubah jawaban di luar kendali saya. Ditambah jika/ketika nulling dioptimalkan keluar itu's sedikit lebih dari fancy komentar jika anda akan.
Saya pikir jika itu membuat saya maksud lebih jelas ke depan bodoh miskin yang mengikuti jejak saya, dan jika itu ,"mungkin" yang berpotensi membantu GC kadang-kadang, maka's layak untuk saya. Sebagian besar itu membuat saya merasa rapi dan jelas, dan Mongo suka merasa rapi dan jelas. :)
Saya melihatnya seperti ini: bahasa Pemrograman yang ada untuk membiarkan orang memberi orang lain gambaran tentang maksud dan compiler pekerjaan permintaan dari apa yang harus dilakukan-compiler mengkonversi permintaan itu ke dalam bahasa yang berbeda (kadang-kadang beberapa) untuk CPU-CPU(s) bisa peduli bahasa apa yang anda gunakan, anda tab pengaturan, komentar, gaya penekanan, nama variabel, dll. -- CPU's semua tentang aliran bit yang menceritakan hal apa yang register dan opcode dan lokasi memori untuk bermalas. Banyak hal yang ditulis dalam kode don't convert ke apa's dikonsumsi oleh CPU dalam urutan yang kita tentukan. Kami C, C++, C#, Cadel, Babel, assembler atau apapun adalah teori daripada realitas, yang ditulis sebagai pernyataan kerja. Apa yang anda lihat bukanlah apa yang anda dapatkan, ya, bahkan dalam bahasa assembler.
Saya mengerti pola pikir "hal yang tidak perlu" (seperti baris kosong) "ini adalah apa-apa tapi suara dan mengacaukan kode." Bahwa saya dalam karir saya, saya benar-benar mendapatkan itu. Pada saat ini saya bersandar ke arah yang membuat kode yang lebih jelas. It's tidak seperti saya'm menambahkan bahkan 50 garis "kebisingan" untuk program saya-itu's beberapa baris di sini atau di sana.
Ada pengecualian untuk setiap aturan. Dalam skenario dengan volatile memory, memori statis, kondisi ras, lajang, penggunaan "basi" data dan semua jenis yang membusuk, yang's yang berbeda: yang anda BUTUHKAN untuk mengelola memori anda sendiri, mengunci dan meniadakan sebagai berhubung karena memori ini bukan bagian dari GC'd Semesta -- mudah-mudahan semua orang memahami itu. Sisa waktu dengan GC'a bahasa itu's soal gaya daripada kebutuhan atau jaminan peningkatan kinerja.
Pada akhir hari, pastikan anda memahami apa yang memenuhi syarat untuk GC dan apa yang's tidak; kunci, membuang, dan membatalkan tepat; lilin; bernapas, bernapas, dan untuk segala sesuatu yang lain saya katakan: Jika hal itu terasa baik, lakukan hal itu. Anda mungkin berbeda...seperti itu harus...
Beberapa objek kira .dispose()
metode yang memaksa sumber daya untuk dihapus dari memori.