C# IDisposable.Dispose()是否应该安全地多次调用?
IDisposable的实现是否应该使Dispose()能够安全地多次调用?还是相反?大多数.NET Framework类都采用什么方法 具体来说,多次调用C# IDisposable.Dispose()是否应该安全地多次调用?,c#,.net,idisposable,C#,.net,Idisposable,IDisposable的实现是否应该使Dispose()能够安全地多次调用?还是相反?大多数.NET Framework类都采用什么方法 具体来说,多次调用System.Data.Linq.DataContext.Dispose()安全吗 我之所以问这个问题,是因为我想知道这种额外的保护是否必要: public override void Dispose(bool disposing) { // Extra protection... if (this.obj != null)
System.Data.Linq.DataContext.Dispose()
安全吗
我之所以问这个问题,是因为我想知道这种额外的保护是否必要:
public override void Dispose(bool disposing)
{
// Extra protection...
if (this.obj != null)
{
this.obj.Dispose();
this.obj = null;
}
// Versus simply...
this.obj.Dispose();
base.Dispose(disposing);
}
在处理类的IDisposable成员时,或者我是否应该只调用
this.obj.Dispose()
,而不考虑以前是否调用过它。您应该可以安全地多次调用它,尽管如果可以,您可能应该避免调用它
从上的MSDN页面:
如果对象的Dispose方法被多次调用,则该对象必须忽略第一次调用之后的所有调用。如果多次调用该对象的Dispose方法,则该对象不得引发异常
是的,IDisposable.Dispose()的实现应该允许多次调用。在第一次调用Dispose()之后,所有其他调用都可以立即返回 我更喜欢代码示例的第一部分,即在运行时处理局部变量并将其设为null
请注意,即使在代码中实现了Dispose和null模式,也可能会多次调用.Dispose()。如果多个使用者持有对同一个一次性对象的引用,则当这些使用者删除对该对象的引用时,该对象的Dispose可能会被调用多次。如果某个对象已被释放,则不应再次处理该对象。这有助于您避免延长垃圾收集器中该对象的使用寿命 我通常使用的模式是这样的
// A base class that implements IDisposable.
// By implementing IDisposable, you are announcing that
// instances of this type allocate scarce resources.
public class BaseClass: IDisposable
{
/// <summary>
/// A value indicating whether this instance of the given entity has
/// been disposed.
/// </summary>
/// <value>
/// <see langword="true"/> if this instance has been disposed; otherwise,
/// <see langword="false"/>.
/// </value>
/// <remarks>
/// If the entity is disposed, it must not be disposed a second
/// time. The isDisposed field is set the first time the entity
/// is disposed. If the isDisposed field is true, then the Dispose()
/// method will not dispose again. This help not to prolong the entity's
/// life in the Garbage Collector.
/// </remarks>
private bool isDisposed;
/// <summary>
/// Disposes the object and frees resources for the Garbage Collector.
/// </summary>
public void Dispose()
{
this.Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
/// <summary>
/// Disposes the object and frees resources for the Garbage Collector.
/// </summary>
/// <param name="disposing">If true, the object gets disposed.</param>
protected virtual void Dispose(bool disposing)
{
if (this.isDisposed)
{
return;
}
if (disposing)
{
// Dispose of any managed resources here.
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// Note disposing is done.
this.isDisposed = true;
}
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~BaseClass()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
}
//实现IDisposable的基类。
//通过实现IDisposable,您宣布
//这种类型的实例分配稀缺资源。
公共类基类:IDisposable
{
///
///一个值,指示给定实体的此实例是否具有
///已经处理好了。
///
///
///如果已处理此实例,则为,
/// .
///
///
///如果该实体已被处置,则不得再次处置该实体
///时间。isDisposed字段是在第一次创建实体时设置的
///如果isDisposed字段为true,则Dispose()
///方法将不再处理。这有助于不延长实体的
///生活在垃圾收集器里。
///
私人住宅被出售;
///
///处置对象并释放垃圾收集器的资源。
///
公共空间处置()
{
这个。处置(真实);
//此对象将通过Dispose方法清除。
//因此,您应该调用GC.superssfalize来
//将此对象从终结队列中移除
//并阻止此对象的终结代码
//从第二次执行开始。
总干事(本);
}
///
///处置对象并释放垃圾收集器的资源。
///
///如果为true,则对象将被释放。
受保护的虚拟void Dispose(bool disposing)
{
如果(此.isDisposed)
{
返回;
}
如果(处置)
{
//在此处处置所有托管资源。
}
//调用适当的方法进行清理
//这里是非托管资源。
//注:处理完成。
this.isDisposed=true;
}
//使用C#析构函数语法完成代码。
//仅当Dispose方法
//没有人打电话。
//它为基类提供了最终确定的机会。
//不要在此类派生的类型中提供析构函数。
~BaseClass()
{
//不要在此处重新创建Dispose清理代码。
//调用Dispose(false)在以下方面是最佳的
//可读性和可维护性。
处置(虚假);
}
}
对象应该允许多次调用Dispose,因为清理代码可能很难确定哪些内容已清理,哪些未清理,尤其是在存在异常的情况下。清除IDisposable字段时将其置零(并容忍已为null的字段)将更容易避免多余的Dispose调用,但使对象容忍多次处理实际上并不需要花费任何成本,而且在某些异常抛出情况下也有助于避免不适。我更喜欢if(!=null)语法。还应使用disposing标志保护聚合对象的dispose。如果对象也有终结器,请确保仅在“disposing”为false时调用this.obj.dispose()。否则,您可能正在从终结器中访问另一个对象,该对象可能已经终结(终结顺序未定义,循环引用没有安全的终结顺序)。如果我是Microsoft,我会将“disposing”标志重命名为“disposedexplicity”或“notInFinalizer”:)第二次处理对象如何延长对象的生存期?垃圾收集器所关心的是是否还有对它的引用。此外,您编写的代码不必要地调用GC.SuppressFinalize(),声称该对象位于终结队列中,但它不在终结队列中,因为它没有终结器。GC不会以任何方式寻找IDisposable(这无论如何都是危险的,因为显式Dispose()可以访问其他对象上的方法,而终结器不应该这样做)。@Cycon:我意识到我没有在你的评论后发布足够完整的代码示例。我所说的延长生命是指它将持续存在于最终确定队列中。我已经更新添加了终结代码,并修复了我发现的另一个小错误。请注意,此模式只应在您实际处理非托管资源时使用,并且您的逻辑可以在不调用ReferenceCI的情况下执行