¿Existe un método, o alguna otra forma liviana, para verificar si una referencia es a un objeto desechado?
PD - Esto es solo una curiosidad (duerma bien, no en código de producción). Sí, sé que puedo detectarlo ObjectDisposedException
al intentar acceder a un miembro del objeto.
c#
.net
dispose
idisposable
Neil C. Obremski
fuente
fuente
bool IsDisposed { get; }
declaración sobreSystem.IDisposable
.Dispose
método ordena a un objeto que libere todos y cada uno de los recursos que ha adquirido pero que aún no ha liberado. Si un objeto nunca contiene recursos, suDispose
método generalmente no tendrá que hacer nada; si el tipo lo declaravoid IDisposable.Dispose() {};
, puede ignorarloIDisposable
sin sobrecarga por instancia. UnaIsDisposed
propiedad que se esperaba que se hiciera verdadera después de cualquierDispose
llamada necesitaría agregar un indicador booleano que de otro modo sería innecesario a cada instancia de muchos tipos que de otro modo se podrían ignorarDispose
.IDisposable
, ¿cómo puede verificar si se ha eliminado primero? ¿En lugar de asumir que no lo es y detectar una excepción? ¿O de alguna manera está destinado a administrar la vida para que siempre sepa si se desecha o no?IsDisposed
bandera puede ayudar a evitar que el código pierda tiempo en operaciones que posiblemente no puedan tener éxito, pero aún así sería necesario manejar excepciones en el caso de que un objeto se elimine entre laIsDisposed
verificación y el intento de usarlo.WeakReference
parece relevante aquí. No es exactamente un detector IDipose'd, pero te dice si es GC'dRespuestas:
No, la implementación predeterminada del patrón IDisposable no lo admite
fuente
System.Windows.Forms.Control
tiene unaIsDisposed
propiedad que se establece en true después de queDispose()
se llame . En sus propios objetos IDisposable, puede crear fácilmente una propiedad similar.fuente
No hay nada integrado que lo permita. Debería exponer una propiedad booleana IsDisposed que refleje una marca de disposición interna.
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); } }
fuente
IDisposablePlus
o lo que sea) que heredaIDisposable
e incluyebool IsDisposed { get; }
. Esto facilita saber cuál de susIDisposable
objetos admiteIsDisposed
.Si no es su clase y no proporciona una propiedad IsDisposed (o algo similar, el nombre es solo una convención), entonces no tiene forma de saberlo.
Pero si es su clase y está siguiendo la implementación canónica IDisposable , simplemente exponga el campo _disposed o _isDisposed como una propiedad y verifique eso.
fuente
El
Dispose
método es necesario para realizar cualquier limpieza necesaria antes de que se abandone un objeto; si no se requiere limpieza, no se requiere hacer nada. Exigir que un objeto realice un seguimiento de si se ha eliminado, incluso cuando elDispose
método no haría nada de otra manera, requeriría que muchosIDisposable
objetos agreguen una bandera para un beneficio muy limitado.Podría haber sido útil
IDisposable
incluir dos propiedades: una que indicaba si un objeto necesitaba desecharse y otra que indicaba que el objeto no se había vuelto inútil por desecho. Para los objetos en los que la eliminación realmente hace algo, ambos valores serían inicialmente verdaderos y luego se volverían falsosDispose
. Para los objetos en los que la eliminación no necesita realizar ninguna limpieza, el primer método siempre podría devolver falso y el segundo siempre verdadero, sin tener que almacenar una bandera en ningún lugar. Sin embargo, no creo que haya ninguna forma de agregarlos a .NET ahora.fuente
IDisposable
que no tiene unaDisposed
propiedad es que se habría percibido como extraño tener objetos en los que llamarDispose
no establecería dicha propiedadtrue
, pero requiriendo que los objetos realicen un seguimiento de siDispose
se llamó en los casos en que de lo contrario, no tendrían razón para preocuparse, lo que sumaría un costo significativo y un beneficio mínimo.Veo que esto es antiguo, pero no vi una respuesta. Algunos no todos los objetos desechables como un DataSet tienen un evento desechado que puede adjuntar.
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; } }
fuente
Disposed
evento es un miembro de laSystem.ComponentModel.IComponent
interfaz.Lo que me gusta hacer es declarar los objetos sin inicializarlos, pero establecer sus valores predeterminados en
Nothing
. Luego, al final del ciclo escribo:If anObject IsNot Nothing Then anObject.Dispose()
Aquí tienes una muestra completa:
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
Esto también funciona muy bien para colocar sus objetos principales en la parte superior de una rutina, usarlos dentro de una
Try
rutina y luego desecharlos en unFinally
bloque: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
fuente
Using
declaración? Eso ciertamente existía en 2013 cuando se escribió esta respuesta.inputPdf
se ha establecido en un valor (que no sea Nada), su respuesta no muestra forma de saber siinputPdf
se ha eliminado. En parte, podría abordar esto colocandoinputPdf = Nothing
después de desechar. Sin embargo, esto no ayudaría a ninguna otra variable que se haya apuntado al mismo objeto queinputPdf
. Esto es, si lo hace:inputPdf = New PdfReader
,Dim pdf2 As PdfReader = inputPdf
,inputPdf.Dispose
,inputPdf = Nothing
, todavía habría ninguna manera de saber quepdf2
está dispuesto (que es el mismo objeto queinputPdf
).