Como é que uma pessoa dizer se uma referência de objeto IDisposable é descartado?
-
08-07-2019 - |
Pergunta
Existe um método, ou alguma outra forma leve, para verificar se a referência é a um objeto descartado?
P.S. - Esta é apenas uma curiosidade (sleep bem, não no código de produção). Sim, eu sei que posso pegar o ObjectDisposedException
ao tentar acessar um membro do objeto.
Solução
Depende, existem objetos IDisposable
que permitem chamar o método Dispose
tanto quanto você quer, e há IDisposable
objetos que ObjectDisposedException
lance. Em tal caso, um desses objetos devem controlar o estado (geralmente implementado com um isDisposed
privado campo booleano).
Outras dicas
Não - implementação padrão do padrão IDisposable não apoiá-lo
System.Windows.Forms.Control
tem um IsDisposed
propriedade que é conjunto para true após Dispose()
é chamado . Em seus próprios objetos IDisposable, você pode facilmente criar uma propriedade semelhante.
Não há nada construído em que irá permitir isso. Você precisaria para expor uma propriedade boolean IsDisposed que reflete uma bandeira dispostos interno.
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);
}
}
Se não for sua classe e ele não fornece uma propriedade IsDisposed. (Ou algo similar - o nome é apenas uma convenção), então você tem nenhuma maneira de saber
Mas se é sua classe e você está seguindo o canônica implementação IDisposable , em seguida, basta expor o campo _disposed ou _isDisposed como uma propriedade e verifique se.
O método Dispose
é necessária para realizar qualquer limpeza será necessária antes de um objeto é abandonado; Se nenhuma limpeza é necessária, não é necessário fazer nada. Exigindo um objeto para controlar se ele foi descartado, mesmo quando o método Dispose
de outra forma, não fazer nada, exigiria muitos IDisposable
objetos para adicionar um sinalizador para benefício muito limitado.
Pode ter sido útil se IDisposable
incluiu duas propriedades - uma que indicou se um objeto necessário descartar , e um dos que indicou que o objeto não tinha sido inutilizados por disposição. Para objetos onde disposição realmente faz alguma coisa, ambos os valores seriam inicialmente verdade, e se tornaria falsa após Dispose
. Para objetos onde disposição não precisa fazer qualquer limpeza, o primeiro método pode sempre retornar falso eo segundo sempre verdadeiro, sem ter que armazenar uma bandeira em qualquer lugar. Eu não acho que há alguma maneira aqueles podem ser adicionados ao .NET agora, no entanto.
Eu vejo isso é velho, mas eu não vi uma resposta. Alguns nem todos os objetos descartáveis ??como um DataSet tem um evento dispostos 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;
}
}
O que eu gostaria de fazer é declarar os objetos sem inicializar-los, mas definir os valores padrão para Nothing
. Então, no final da gravação ciclo I:
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 os seus principais objetos no topo de uma rotina, utilizando-os dentro de uma rotina Try
, e depois descartá-los em um bloco 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