Existe um método, ou alguma outra forma leve, para verificar se uma referência é a um objeto descartado?
PS - Isso é apenas uma curiosidade (durma bem, não em código de produção). Sim, eu sei que posso pegar o ObjectDisposedException
ao tentar acessar um membro do objeto.
c#
.net
dispose
idisposable
Neil C. Obremski
fonte
fonte
bool IsDisposed { get; }
declaração sobreSystem.IDisposable
.Dispose
método direciona um objeto para liberar todo e qualquer recurso adquirido, mas ainda não liberado. Se um objeto nunca mantém recursos, seuDispose
método geralmente não precisa fazer nada; se o tipo declara,void IDisposable.Dispose() {};
ele pode, de outra forma, ignorarIDisposable
sem sobrecarga por instância. UmaIsDisposed
propriedade que deveria se tornar verdadeira após qualquerDispose
chamada necessitaria adicionar um sinalizador booleano desnecessário a cada instância de muitos tipos que poderiam ser ignoradosDispose
.IDisposable
, como você pode verificar se ele foi descartado primeiro? Em vez de presumir que não é e capturar uma exceção? Ou, de alguma forma, você deve administrar a vida toda para que sempre saiba se ela está descartada ou não?IsDisposed
sinalizador pode ajudar a evitar que o código perca tempo em operações que possivelmente não serão bem-sucedidas, mas ainda seria necessário lidar com exceções no caso de um objeto ser descartado entre aIsDisposed
verificação e a tentativa de usá-lo.WeakReference
parece relevante aqui. Não é exatamente um detector IDipose, mas indica se é GCRespostas:
Não - a implementação padrão do padrão IDisposable não o suporta
fonte
System.Windows.Forms.Control
tem umaIsDisposed
propriedade que é definida como true apósDispose()
ser chamada . Em seus próprios objetos IDisposable, você pode criar facilmente uma propriedade semelhante.fonte
Não há nada embutido que permita isso. Você precisaria expor uma propriedade booleana IsDisposed que reflete um sinalizador interno descartado.
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); } }
fonte
IDisposablePlus
ou qualquer outra) que herdaIDisposable
e incluibool IsDisposed { get; }
. Isso facilita saber quais dos seusIDisposable
objetos suportamIsDisposed
.Se não for sua classe e não fornecer uma propriedade IsDisposed (ou algo semelhante - o nome é apenas uma convenção), você não tem como saber.
Mas se for sua classe e você estiver seguindo a implementação canônica de IDisposable , então apenas exponha o campo _disposed ou _isDisposed como uma propriedade e verifique isso.
fonte
O
Dispose
método é necessário para realizar qualquer limpeza necessária antes que um objeto seja abandonado; se nenhuma limpeza for necessária, não é necessário fazer nada. Exigir que um objeto rastreie se ele foi descartado, mesmo quando oDispose
método não faria nada de outra forma, exigiria que muitosIDisposable
objetos adicionassem um sinalizador para um benefício muito limitado.Poderia ter sido útil
IDisposable
incluir duas propriedades - uma que indicava se um objeto precisava ser descartado e uma que indicava que o objeto não havia se tornado inútil pelo descarte. Para objetos em que o descarte realmente faz algo, ambos os valores seriam inicialmente verdadeiros e se tornariam falsos depoisDispose
. Para objetos em que o descarte não precisa fazer nenhuma limpeza, o primeiro método sempre pode retornar falso e o segundo sempre verdadeiro, sem ter que armazenar um sinalizador em qualquer lugar. Não acho que haja alguma maneira de adicioná-los ao .NET agora.fonte
IDisposable
não ter umaDisposed
propriedade é que teria sido percebido como estranho ter objetos para os quais a chamadaDispose
não definiria tal propriedadetrue
, mas exigindo que os objetos controlassem seDispose
foi chamado nos casos em que caso contrário, eles não teriam motivo para se preocupar, acrescentariam custos significativos e poucos benefícios.Vejo que isso é antigo, mas não vi uma resposta. Alguns nem todos os objetos descartáveis, como um DataSet, têm um evento descartado que você pode anexar.
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; } }
fonte
Disposed
evento é um membro daSystem.ComponentModel.IComponent
interface.O que eu gosto de fazer é declarar os objetos sem inicializá-los, mas definir seus valores padrão para
Nothing
. Então, no final do loop, escrevo:If anObject IsNot Nothing Then anObject.Dispose()
Aqui está um exemplo completo:
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
Isso também funciona muito bem para colocar seus objetos principais no topo de uma rotina, usá-los dentro de uma
Try
rotina e, em seguida, descartá-los em umFinally
bloco: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
fonte
Using
declaração? Isso certamente existia em 2013, quando esta resposta foi escrita.inputPdf
ter sido definido com um valor (diferente de Nothing), sua resposta não mostra como saber seinputPdf
foi descartado. Você poderia resolver isso parcialmente definindoinputPdf = Nothing
após o descarte. No entanto, isso não ajudaria em nenhuma outra variável que tenha sido apontada para o mesmo objeto queinputPdf
. Isto é, se você faz:inputPdf = New PdfReader
,Dim pdf2 As PdfReader = inputPdf
,inputPdf.Dispose
,inputPdf = Nothing
, ainda haveria nenhuma maneira de saber quepdf2
está disposto (é o mesmo objetoinputPdf
).