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
How does one tell if an IDisposable object reference is disposed?
提问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 ObjectDisposedException
upon 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.Control
has an IsDisposed
property 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
有一个在被调用后设置为 true的IsDisposed
属性。在您自己的 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 Try
routine, and then disposing them in a Finally
block:
这也非常适合将主要对象放在例程的顶部,在例程中使用它们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 Dispose
method 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 Dispose
method would otherwise do nothing, would require many IDisposable
objects to add a flag for very limited benefit.
该Dispose
方法需要在放弃对象之前执行所需的任何清理工作;如果不需要清理,则不需要执行任何操作。要求一个对象跟踪它是否已被释放,即使该Dispose
方法在其他情况下什么都不做,也需要许多IDisposable
对象添加一个标志以获得非常有限的好处。
It might have been helpful if IDisposable
included 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;
}
}