是否有一种方法或其他轻量级的方法来检查引用是否指向已处置的物体?
PS-这只是一种好奇(睡得好,不在生产代码中)。是的,我知道我可以ObjectDisposedException
尝试访问该对象的成员。
是否有一种方法或其他轻量级的方法来检查引用是否指向已处置的物体?
PS-这只是一种好奇(睡得好,不在生产代码中)。是的,我知道我可以ObjectDisposedException
尝试访问该对象的成员。
Dispose
方法指示对象释放其已获取但尚未释放的所有资源。如果对象从不拥有资源,则其Dispose
方法通常无需执行任何操作。如果类型声明,void IDisposable.Dispose() {};
则可以忽略IDisposable
每个实例,而不会产生每个实例的开销。IsDisposed
预期在任何Dispose
调用后变为true的属性将有必要向许多本可以忽略的许多类型的每个实例添加一个不必要的布尔标志Dispose
。
IDisposable
,如何检查它是否已被先处理掉?而不是假设它不是并捕获异常?还是以某种方式管理生命周期,以便您始终应该知道它是否已废弃?
IsDisposed
标志可以帮助防止代码上不可能成功操作浪费时间,但人们仍需要一个对象被置于之间的情况来处理异常IsDisposed
检查,并使用它的尝试。
WeakReference
在这里似乎相关。这是不完全的IDipose'd探测器,但它并告诉你,如果它是GC'd
Answers:
System.Windows.Forms.Control
具有的IsDisposed
属性,该属性在Dispose()
调用后设置为true。在您自己的IDisposable对象中,您可以轻松创建类似的属性。
没有内置的功能可以做到这一点。您需要公开一个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);
}
}
IDisposablePlus
继承自IDisposable
并包括的新接口(或其他任何接口)bool IsDisposed { get; }
。这样就很容易知道您的IDisposable
对象支持哪些对象IsDisposed
。
如果不是您的类,并且没有提供IsDisposed属性(或类似的东西-名称仅是约定),那么您将无所适从。
但是,如果这是您的类,并且您正在遵循规范的IDisposable实现,则只需将_disposed或_isDisposed字段公开为属性并进行检查即可。
在Dispose
放弃对象之前,需要使用该方法执行所需的任何清理工作;如果不需要清理,则无需执行任何操作。即使该Dispose
方法原本不采取任何措施,要求一个对象来跟踪其是否已被处置,也将需要许多IDisposable
对象添加一个标志,以获取非常有限的收益。
如果IDisposable
包括两个属性,可能会有所帮助:一个属性指示是否需要处置某个对象,另一个属性指示该对象并未因处置而变得无用。对于实际上可以处理的对象,两个值最初都是true,之后是false Dispose
。对于不需要进行任何清理的对象,第一种方法可以始终返回false,第二种方法始终可以为true,而不必在任何地方存储标志。我不认为现在可以将它们添加到.NET中。
IDisposable
没有Disposed
属性的主要原因是,在Dispose
没有将调用设置为此类属性的对象的情况下,将其视为奇怪的事情true
,但是要求对象跟踪Dispose
在以下情况下是否调用了该对象否则他们将没有理由去照料,这会增加可观的成本,却几乎没有收益。
我看到这很旧,但是没有看到答案。并非所有一次性对象(例如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;
}
}
Disposed
事件是System.ComponentModel.IComponent
接口的成员。
我想做的是声明对象而不初始化它们,但是将它们的默认值设置为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
Using
语句就执行所有这些操作?早在2013年撰写此答案时,确实存在这种情况。
inputPdf
将其设置为值(Nothing除外),您的答案将无法显示是否inputPdf
已处置的方法。您可以通过处理后进行设置来部分解决此问题inputPdf = Nothing
。但是,这对任何其他指向与相同对象的变量都没有帮助inputPdf
。也就是说,如果你这样做: inputPdf = New PdfReader
,Dim pdf2 As PdfReader = inputPdf
,inputPdf.Dispose
,inputPdf = Nothing
,仍然会有没有办法知道,pdf2
被布置(它是相同的对象inputPdf
)。
bool IsDisposed { get; }
声明System.IDisposable
。