如何判断是否配置了IDisposable对象引用?

时间:2008-10-10 16:44:05

标签: c# .net dispose idisposable

是否有方法或其他轻量级方法来检查引用是否属于被处置对象?

P.S。 - 这只是一种好奇心(睡得好,不在生产代码中)。是的,我知道在尝试访问该对象的成员时我可以捕获ObjectDisposedException

9 个答案:

答案 0 :(得分:44)

否 - IDisposable模式的默认实现不支持

答案 1 :(得分:38)

System.Windows.Forms.Control的{​​{3}}属性为IsDisposed。在您自己的IDisposable对象中,您可以轻松创建类似的属性。

答案 2 :(得分:18)

内置任何东西都不会允许这样做。您需要公开反映内部置位标志的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);
    }
}

答案 3 :(得分:9)

如果它不是你的类,并且它没有提供IsDisposed属性(或类似的东西 - 名称只是一个约定),那么你无法知道。

但是如果它是你的班级并且你正在关注canonical IDisposable implementation,那么只需将_disposed或_isDisposed字段作为属性公开并检查它。

答案 4 :(得分:2)

在放弃对象之前,需要Dispose方法来执行所需的清理工作;如果不需要清理,则不需要做任何事情。要求一个对象跟踪它是否已被处置,即使Dispose方法无效,也需要许多IDisposable个对象添加一个标志,以获得非常有限的好处。

如果IDisposable包含两个属性 - 一个指示对象是否需要处理,另一个指示该对象未被呈现,则可能会有所帮助无用的处置。对于处理实际上做某事的对象,这两个值最初都是真的,并且在Dispose之后会变为假。对于处理不需要进行任何清理的对象,第一种方法总是返回false而第二种方法总是为真,而不必在任何地方存储标志。我认为现在没有任何方法可以添加到.NET中。

答案 5 :(得分:1)

我看到这很旧,但没有看到答案。 并非某些一次性对象(例如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;
    }
}

答案 6 :(得分:0)

检查对象是否使用扩展方法处理的快捷方式可能是

public static class ObjectExtensions 
{
    public static bool IsDisposed(this object obj)
    {
        try
        {
            obj.ToString();
            return false;
        }
        catch (ObjectDisposedException)
        {
            return true;
        }
    }

}

//Usage
if(myObject.IsDisposed()){ 
    /* Do your Stuff */ 
}

答案 7 :(得分:-1)

我喜欢做的是声明对象而不初始化它们,但是将它们的默认值设置为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

答案 8 :(得分:-16)

这取决于,有IDisposable个对象允许根据需要调用Dispose方法,并且有IDisposable个对象抛出ObjectDisposedException。在这种情况下,这些对象必须跟踪状态(通常使用私有布尔字段isDisposed实现)。