Есть ли метод или какой-то другой легкий способ проверить, есть ли ссылка на удаленный объект?
PS - Это просто любопытство (спи спокойно, а не в продакшене). Да, я знаю, что могу поймать это ObjectDisposedException
при попытке доступа к члену объекта.
c#
.net
dispose
idisposable
Нил С. Обремски
источник
источник
bool IsDisposed { get; }
декларацииSystem.IDisposable
.Dispose
метод предписывает объекту освободить все ресурсы, которые он получил, но еще не освободил. Если объект никогда не содержит ресурсов, егоDispose
метод обычно ничего не делает; если тип заявляет,void IDisposable.Dispose() {};
что в противном случае он может игнорироватьIDisposable
без дополнительных затрат на каждый экземпляр.IsDisposed
Имущество , которое , как ожидается, станет истинным после любогоDispose
вызова потребует добавлений в противном случае, ненужный логический флаг для каждого экземпляра многих видов , которые могли бы игнорироватьDispose
.IDisposable
, как вы можете сначала проверить, был ли он удален? Вместо того, чтобы предполагать, что это не так, и ловить исключение? Или каким-то образом вы должны управлять сроком службы, чтобы всегда знать, утилизировано оно или нет?IsDisposed
Флаг может помочь предотвратить код от траты времени на операции, не может добиться успеха, но один все еще нужно обрабатывать исключения в случае , если объект получает расположенный междуIsDisposed
проверкой и попыткой использовать его.WeakReference
кажется здесь актуальным. Это не совсем детектор IDipose'd, но он говорит вам, если он GC'dОтветы:
Нет - реализация шаблона IDisposable по умолчанию не поддерживает его
источник
System.Windows.Forms.Control
имеетIsDisposed
свойство, для которого устанавливается значение true послеDispose()
вызова . В ваших собственных объектах IDisposable вы можете легко создать подобное свойство.источник
Нет ничего, что позволяло бы это сделать. Вам нужно будет предоставить логическое свойство IsDisposed, которое отражает внутренний удаленный флаг.
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); } }
источник
IDisposablePlus
или любой другой), который наследуется отIDisposable
и включаетbool IsDisposed { get; }
. Это позволяет легко узнать, какие из вашихIDisposable
объектов поддерживаютIsDisposed
.Если это не ваш класс и он не предоставляет свойство IsDisposed (или что-то подобное - это просто соглашение), у вас нет возможности узнать.
Но если это ваш класс и вы следуете канонической реализации IDisposable , тогда просто предоставьте поле _disposed или _isDisposed как свойство и проверьте это.
источник
Dispose
Метод требуется выполнить все , что очистка будет необходимо , прежде чем объект прекращается; если очистка не требуется, ничего делать не требуется. Требование от объекта отслеживать, был ли он удален, даже если вDispose
противном случае метод ничего бы не сделал, потребовало бы, чтобы многиеIDisposable
объекты добавляли флаг для очень ограниченной выгоды.Было бы полезно, если бы в него были
IDisposable
включены два свойства: одно указывало, нужно ли удалять объект , а другое указывало, что объект не стал бесполезным в результате удаления. Для объектов, в которых удаление действительно что-то делает, оба значения будут изначально истинными, а затем станут ложнымиDispose
. Для объектов, удаление которых не требует какой-либо очистки, первый метод всегда может возвращать false, а второй всегда true, без необходимости хранить флаг где-либо. Однако я не думаю, что есть какой-либо способ добавить их в .NET сейчас.источник
IDisposable
отсутствияDisposed
свойства заключается в том, что было бы странно иметь объекты, вызовDispose
которых не установил бы такое свойствоtrue
, но требовал, чтобы объекты отслеживали,Dispose
был ли вызван в случаях, когда в противном случае у них не было бы причин для беспокойства, это привело бы к значительным затратам и незначительной выгоде.Я вижу, что это старый, но я не видел ответа. Некоторые не все одноразовые объекты, такие как DataSet, имеют удаленное событие, которое вы можете прикрепить.
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; } }
источник
Disposed
событие является членомSystem.ComponentModel.IComponent
интерфейса.Мне нравится объявлять объекты без их инициализации, но устанавливать для них значения по умолчанию
Nothing
. Затем в конце цикла я пишу:If anObject IsNot Nothing Then anObject.Dispose()
Вот полный образец:
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
Это также отлично подходит для размещения ваших основных объектов в начале процедуры, использования их внутри
Try
процедуры, а затем размещения их вFinally
блоке: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
источник
Using
оператора? Это определенно существовало еще в 2013 году, когда был написан этот ответ.inputPdf
как было установлено значение (кроме Nothing), ваш ответ не показывает способа узнать, было лиinputPdf
удалено. Вы можете частично решить эту проблему, установивinputPdf = Nothing
после утилизации. Однако это не поможет другим переменным, которые были указаны на тот же объект, что иinputPdf
. То есть , если вы делаете:inputPdf = New PdfReader
,Dim pdf2 As PdfReader = inputPdf
,inputPdf.Dispose
,inputPdf = Nothing
, не было еще никакого способа узнать , чтоpdf2
расположена (это тот же объектinputPdf
).