C# 如何判断 IDisposable 对象引用是否已释放?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/192206/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:27:28  来源:igfitidea点击:

How does one tell if an IDisposable object reference is disposed?

c#.netdisposeidisposable

提问by Neil C. Obremski

Is there a method, or some other light-weight way, to check if a reference is to a disposed object?

有没有一种方法或其他一些轻量级的方法来检查引用是否是对已处理对象的引用?

P.S. - This is just a curiousity (sleep well, not in production code). Yes, I know I can catch the ObjectDisposedExceptionupon trying to access a member of the object.

PS - 这只是一个好奇(睡个好觉,不是在生产代码中)。是的,我知道我可以ObjectDisposedException在尝试访问对象成员时捕捉到。

回答by Dandikas

No - default implementation of IDisposable pattern does not support it

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

回答by Ryan Lundy

System.Windows.Forms.Controlhas an IsDisposedproperty which is set to true after Dispose()is called. In your own IDisposable objects, you can easily create a similar property.

System.Windows.Forms.Control有一个被调用后设置为 trueIsDisposed属性。在您自己的 IDisposable 对象中,您可以轻松地创建类似的属性。Dispose()

回答by jop

If it is not your class and it doesn't provide an IsDisposed property (or something similar - the name is just a convention), then you have no way of knowing.

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

But if it is your class and you are following the canonical IDisposable implementation, then just expose the _disposed or _isDisposed field as a property and check that.

但是如果它是你的类并且你遵循规范的 IDisposable implementation,那么只需将 _disposed 或 _isDisposed 字段公开为一个属性并检查它。

回答by Scott Dorman

There is nothing built in that will allow this. You would need to expose an IsDisposed boolean property that reflects an internal disposed flag.

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

回答by JeffreyDurham

What I like to do is declare the objects without initializing them, but set their default values to Nothing. Then, at the end of the loop I write:

我喜欢做的是声明对象而不初始化它们,但将它们的默认值设置为Nothing. 然后,在循环结束时我写:

If anObject IsNot Nothing Then anObject.Dispose()

Here is a complete sample:

这是一个完整的示例:

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

This also works great for putting your main objects at the top of a routine, using them inside a Tryroutine, and then disposing them in a Finallyblock:

这也非常适合将主要对象放在例程的顶部,在例程中使用它们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

回答by supercat

The Disposemethod is required to perform whatever cleanup will be required before an object is abandoned; if no cleanup is required, it is not required to do anything. Requiring an object to keep track of whether it has been disposed, even when the Disposemethod would otherwise do nothing, would require many IDisposableobjects to add a flag for very limited benefit.

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

It might have been helpful if IDisposableincluded two properties--one which indicated whether an object needed disposing, and one of which indicated that the object had not been rendered uselessby disposal. For objects where disposal actually does something, both values would be initially true, and would become false after Dispose. For objects where disposal doesn't need to do any cleanup, the first method could always return false and the second one always true, without having to store a flag anywhere. I don't think there's any way those can be added to .NET now, though.

如果IDisposable包含两个属性可能会有所帮助- 一个指示对象是否需要 dispose,其中一个指示对象没有因处理而变得无用。对于处理实际执行某些操作的对象,两个值最初都为真,并且在 之后变为假Dispose。对于不需要进行任何清理的对象,第一种方法可以始终返回 false,而第二种方法始终为 true,而无需在任何地方存储标志。不过,我认为现在没有任何方法可以将这些添加到 .NET 中。

回答by Moses

I see this is old, but I did not see an answer. Some not all disposable objects like a DataSet have a disposed event you can attach.

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