Kapan saya mengimplementasikan IDispose di kelas sebagai lawan dari destruktor? Saya membaca artikel ini , tetapi saya masih kehilangan intinya.
Asumsi saya adalah bahwa jika saya mengimplementasikan IDispose pada suatu objek, saya dapat secara eksplisit 'merusak' sebagai lawan menunggu pengumpul sampah untuk melakukannya. Apakah ini benar?
Apakah itu berarti saya harus selalu secara eksplisit memanggil Buang pada suatu objek? Apa saja contoh umum dari ini?
c#
.net
dispose
destructor
Jordan Parmer
sumber
sumber
using
konstruksi.Jawaban:
Finalizer (alias destruktor) adalah bagian dari pengumpulan sampah (GC) - tidak dapat ditentukan ketika (atau bahkan jika) ini terjadi, karena GC terutama terjadi sebagai akibat dari tekanan memori (yaitu membutuhkan lebih banyak ruang). Finalizer biasanya hanya digunakan untuk membersihkan sumber daya yang tidak dikelola , karena sumber daya yang dikelola akan memiliki pengumpulan / pembuangannya sendiri.
Karenanya
IDisposable
digunakan untuk membersihkan objek secara deterministik , yaitu sekarang. Itu tidak mengumpulkan memori objek (yang masih milik GC) - tetapi digunakan misalnya untuk menutup file, koneksi database, dll.Ada banyak topik sebelumnya tentang ini:
Terakhir, perhatikan bahwa tidak jarang suatu
IDisposable
objek juga memiliki finalizer; dalam hal ini,Dispose()
biasanya panggilanGC.SuppressFinalize(this)
, yang berarti bahwa GC tidak menjalankan finalizer - itu hanya membuang memori (jauh lebih murah). Finalizer tetap berjalan jika Anda lupaDispose()
objeknya.sumber
Peran
Finalize()
metode ini adalah untuk memastikan bahwa objek .NET dapat membersihkan sumber daya yang tidak dikelola saat sampah dikumpulkan . Namun, objek seperti koneksi database atau penangan file harus dirilis sesegera mungkin, alih-alih mengandalkan pengumpulan sampah. Untuk itu Anda harus mengimplementasikanIDisposable
antarmuka, dan melepaskan sumber daya Anda dalamDispose()
metode tersebut.sumber
Ada deskripsi yang sangat bagus tentang MSDN :
sumber
Satu-satunya hal yang harus ada di destruktor C # adalah baris ini:
Itu dia. Tidak ada hal lain yang harus dilakukan dalam metode itu.
sumber
Pertanyaan Anda tentang apakah Anda harus selalu menelepon atau tidak
Dispose
biasanya merupakan perdebatan sengit. Lihat blog ini untuk perspektif yang menarik dari individu yang dihormati di komunitas .NET.Secara pribadi, saya pikir posisi Jeffrey Richter bahwa panggilan
Dispose
tidak wajib sangatlah lemah. Dia memberikan dua contoh untuk membenarkan pendapatnya.Dalam contoh pertama, dia mengatakan memanggil
Dispose
kontrol Windows Forms membosankan dan tidak perlu dalam skenario umum. Namun, ia gagal menyebutkan bahwaDispose
sebenarnya dipanggil secara otomatis oleh wadah kontrol dalam skenario arus utama tersebut.Dalam contoh kedua dia menyatakan bahwa pengembang mungkin salah berasumsi bahwa instance dari
IAsyncResult.WaitHandle
harus dibuang secara agresif tanpa menyadari bahwa properti dengan malas menginisialisasi pegangan tunggu yang mengakibatkan penalti kinerja yang tidak perlu. Tapi, masalah dengan contoh ini adalah bahwaIAsyncResult
itu sendiri tidak mematuhi pedoman yang diterbitkan Microsoft sendiri untuk menanganiIDisposable
objek. Yaitu jika sebuah kelas memiliki referensi ke suatuIDisposable
tipe maka kelas itu sendiri harus diimplementasikanIDisposable
. JikaIAsyncResult
mengikuti aturan itu makaDispose
metodenya sendiri bisa membuat keputusan mengenai anggota konstituen mana yang perlu dibuang.Jadi, kecuali seseorang memiliki argumen yang lebih meyakinkan, saya akan tetap berada di kamp "selalu hubungi Buang" dengan pemahaman bahwa akan ada beberapa kasus pinggiran yang sebagian besar muncul karena pilihan desain yang buruk.
sumber
Ini sangat sederhana. Saya tahu ini telah dijawab tetapi saya akan mencoba lagi tetapi akan mencoba membuatnya sesederhana mungkin.
Penghancur biasanya tidak pernah digunakan. Ini hanya dijalankan .net ingin dijalankan. Ini hanya akan berjalan setelah siklus collectoin sampah. Ini mungkin tidak pernah benar-benar dijalankan selama siklus hidup aplikasi Anda. Untuk alasan ini, Anda tidak boleh memasukkan kode apa pun ke dalam destruktor yang 'harus' dijalankan. Anda juga tidak dapat mengandalkan objek apa pun yang ada di dalam kelas agar ada saat dijalankan (objek tersebut mungkin sudah dibersihkan karena urutan pengrusakan yang dijalankan tidak dijamin).
IDisposible harus digunakan setiap kali Anda memiliki objek yang membuat sumber daya yang perlu dibersihkan (misalnya, pegangan file dan grafik). Faktanya, banyak yang berpendapat bahwa apa pun yang Anda masukkan ke dalam destruktor harus dimasukkan ke IDdisposable karena alasan yang tercantum di atas.
Sebagian besar kelas akan memanggil dispose ketika finalizer dijalankan tetapi ini hanya ada sebagai penjaga yang aman dan tidak boleh diandalkan. Anda harus secara eksplisit membuang apa pun yang mengimplementasikan IDisposable setelah Anda selesai melakukannya. Jika Anda menerapkan IDisposable, Anda harus memanggil dispose di finalizer. Lihat http://msdn.microsoft.com/en-us/library/system.idisposable.aspx untuk contoh.
sumber
Berikut adalah artikel bagus lainnya yang membersihkan beberapa kabut di sekitar IDisposable, GC dan buang.
Chris Lyons WebLog Demystifying Buang
sumber