Adakah metode, atau cara ringan lainnya, untuk memeriksa apakah referensi ditujukan ke benda yang dibuang?
PS - Ini hanya keingintahuan (tidur nyenyak, bukan dalam kode produksi). Ya, saya tahu saya dapat menangkap ObjectDisposedException
saat mencoba mengakses anggota objek.
c#
.net
dispose
idisposable
Neil C. Obremski
sumber
sumber
bool IsDisposed { get; }
deklarasi tentangSystem.IDisposable
.Dispose
Metode ini mengarahkan objek untuk melepaskan setiap dan semua sumber daya yang telah diperolehnya tetapi belum dirilis. Jika sebuah objek tidak pernah memiliki sumber daya,Dispose
metodenya umumnya tidak perlu melakukan apapun; jika tipe mendeklarasikannya,void IDisposable.Dispose() {};
ia dapat mengabaikannyaIDisposable
tanpa overhead per instance. SebuahIsDisposed
properti yang diharapkan menjadi benar mengikuti setiapDispose
panggilan akan memerlukan menambahkan bendera Boolean dinyatakan-tidak perlu untuk setiap contoh dari banyak jenis yang lain bisa mengabaikanDispose
.IDisposable
, bagaimana Anda bisa memeriksa apakah itu telah dibuang terlebih dahulu? Daripada berasumsi bahwa itu bukan dan menangkap pengecualian? Atau entah bagaimana Anda ditakdirkan untuk mengatur kehidupan sehingga Anda harus selalu tahu apakah itu dibuang atau tidak?IsDisposed
bendera dapat membantu mencegah kode dari membuang-buang waktu pada operasi yang tidak mungkin berhasil, tapi satu masih perlu untuk menangani pengecualian dalam kasus sebuah benda akan dibuang antaraIsDisposed
cek dan upaya untuk menggunakannya.WeakReference
tampaknya relevan di sini. Ini sebenarnya bukan detektor IDipose, tetapi ini memberi tahu Anda apakah itu GC'dJawaban:
Tidak - implementasi default dari pola IDisposable tidak mendukungnya
sumber
System.Windows.Forms.Control
memilikiIsDisposed
properti yang disetel ke true setelahDispose()
dipanggil . Di objek IDisposable Anda sendiri, Anda dapat dengan mudah membuat properti serupa.sumber
Tidak ada bawaan yang memungkinkan hal ini. Anda perlu mengekspos properti boolean IsDisposed yang mencerminkan bendera pembuangan internal.
public class SimpleCleanup : IDisposable { private bool disposed = false; public bool IsDisposed { get { return disposed; } } public SimpleCleanup() { this.handle = /*...*/; } protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { // free only managed resources here } // free unmanaged resources here disposed = true; } } public void Dispose() { Dispose(true); } }
sumber
IDisposablePlus
atau apa pun) yang mewarisiIDisposable
dan menyertakanbool IsDisposed { get; }
. Ini memudahkan untuk mengetahui objek mana yangIDisposable
mendukungIsDisposed
.Jika itu bukan kelas Anda dan tidak menyediakan properti IsDisposed (atau sesuatu yang serupa - namanya hanyalah konvensi), maka Anda tidak tahu.
Tetapi jika itu adalah kelas Anda dan Anda mengikuti implementasi IDisposable kanonik , maka cukup perlihatkan bidang _disposed atau _isDisposed sebagai properti dan periksa.
sumber
The
Dispose
metode diperlukan untuk melakukan pembersihan apapun akan diperlukan sebelum sebuah benda ditinggalkan; jika tidak diperlukan pembersihan, Anda tidak perlu melakukan apa pun. Mewajibkan sebuah objek untuk melacak apakah telah dibuang, bahkan ketikaDispose
metode tersebut tidak akan melakukan apa-apa, akan membutuhkan banyak halIDisposable
objek untuk menambahkan tanda untuk manfaat yang sangat terbatas.Mungkin akan membantu jika
IDisposable
menyertakan dua properti - satu yang menunjukkan apakah suatu objek perlu dibuang , dan salah satunya menunjukkan bahwa objek tersebut tidak dianggap tidak berguna dengan pembuangan. Untuk objek di mana pembuangan benar-benar melakukan sesuatu, kedua nilai awalnya adalah benar, dan menjadi salah setelahnyaDispose
. Untuk objek yang pembuangannya tidak perlu melakukan pembersihan apa pun, metode pertama selalu dapat mengembalikan false dan yang kedua selalu benar, tanpa harus menyimpan tanda di mana pun. Saya rasa tidak ada cara untuk menambahkannya ke .NET sekarang.sumber
IDisposable
tidak memilikiDisposed
properti adalah karena akan dianggap aneh memiliki objek di mana pemanggilanDispose
tidak akan menyetel properti seperti itutrue
, tetapi mengharuskan objek tersebut melacak apakahDispose
dipanggil dalam kasus di mana jika tidak mereka tidak punya alasan untuk peduli akan menambah biaya yang signifikan dan sedikit manfaat.Saya melihat ini sudah tua, tetapi saya tidak melihat jawabannya. Beberapa tidak semua objek sekali pakai seperti DataSet memiliki acara pembuangan yang dapat Anda lampirkan.
class DisposeSample : IDisposable { DataSet myDataSet = new DataSet(); private bool _isDisposed; public DisposeSample() { // attach dispose event for myDataSet myDataSet.Disposed += MyDataSet_Disposed; } private void MyDataSet_Disposed(object sender, EventArgs e) { //Event triggers when myDataSet is disposed _isDisposed = true; // set private bool variable as true } public void Dispose() { if (!_isDisposed) // only dispose if has not been disposed; myDataSet?.Dispose(); // only dispose if myDataSet is not null; } }
sumber
Disposed
acara adalah anggotaSystem.ComponentModel.IComponent
antarmuka.Yang ingin saya lakukan adalah mendeklarasikan objek tanpa menginisialisasi, tetapi menyetel nilai defaultnya ke
Nothing
. Kemudian, di akhir loop saya menulis:If anObject IsNot Nothing Then anObject.Dispose()
Berikut contoh lengkapnya:
Public Sub Example() Dim inputPdf As PdfReader = Nothing, inputDoc As Document = Nothing, outputWriter As PdfWriter = Nothing 'code goes here that may or may not end up using all three objects, ' such as when I see that there aren't enough pages in the pdf once I open ' the pdfreader and then abort by jumping to my cleanup routine using a goto .. GoodExit: If inputPdf IsNot Nothing Then inputPdf.Dispose() If inputDoc IsNot Nothing Then inputDoc.Dispose() If outputWriter IsNot Nothing Then outputWriter.Dispose() End Sub
Ini juga berfungsi dengan baik untuk menempatkan objek utama Anda di bagian atas rutinitas, menggunakannya di dalam
Try
rutinitas, dan kemudian membuangnya dalam satuFinally
blok:Private Sub Test() Dim aForm As System.Windows.Forms.Form = Nothing Try Dim sName As String = aForm.Name 'null ref should occur Catch ex As Exception 'got null exception, no doubt Finally 'proper disposal occurs, error or no error, initialized or not.. If aForm IsNot Nothing Then aForm.Dispose() End Try End Sub
sumber
Using
pernyataan? Itu pasti ada di tahun 2013 ketika jawaban ini ditulis.inputPdf
ditetapkan ke nilai (selain Tidak Ada), jawaban Anda tidak menunjukkan cara untuk mengetahui apakahinputPdf
telah dibuang. Anda dapat mengatasinya sebagian dengan mengaturinputPdf = Nothing
setelah membuang. Namun ini tidak akan membantu variabel lain yang telah diarahkan ke objek yang samainputPdf
. Itu jika Anda lakukan:inputPdf = New PdfReader
,Dim pdf2 As PdfReader = inputPdf
,inputPdf.Dispose
,inputPdf = Nothing
, ada masih akan ada cara untuk mengetahui bahwapdf2
dibuang (itu adalah objek yang sama sepertiinputPdf
).