C# IDisposable GC.SuppressFinalize(此)位置
我对代码使用默认的IDisposable实现模板(模式) 片段:C# IDisposable GC.SuppressFinalize(此)位置,c#,.net,idisposable,suppressfinalize,C#,.net,Idisposable,Suppressfinalize,我对代码使用默认的IDisposable实现模板(模式) 片段: public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool isDisposing) { if (!this.disposed) { if (isDisposing) { //cleanup m
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool isDisposing)
{
if (!this.disposed)
{
if (isDisposing)
{
//cleanup managed resources
}
//cleanup unmanaged resources
this.disposed = true;
}
}
我的问题:为什么在Dispose公共方法中调用“GC.SuppressFinalize(this)”?在处理托管资源之后,我会将“GC.SuppressFinalize(this)”放在受保护方法的“if(isDisposing)”部分
像这样:
protected virtual void Dispose(bool isDisposing)
{
if (!this.disposed)
{
if (isDisposing)
{
//cleanup managed resources
GC.SuppressFinalize(this);
}
//cleanup unmanaged resources
this.disposed = true;
}
}
其思想是清理代码只应调用一次。但是,有两个入口点:
Dispose
方法和对象终结器。调用Dispose
时,您选择退出终结,以便只调用一次清理代码。这本书也许能更好地说明这一点
引述:
// NOTE: Leave out the finalizer altogether if this class doesn't
// own unmanaged resources itself, but leave the other methods
// exactly as they are.
我认为可以选择任何一种布局,但可能他们想在受保护的Dispose方法中强调“将所有释放代码放在这个方法中”,所以他们将另一个disposing工件(抑制终结)放在其他地方
另外,假设一个派生类调用受保护的Dispose方法还有另一个原因,但仍然希望发生终结(无论出于何种想象的原因,我不知道)。我想这显然是一种模板设计模式 您的抽象类设计用于处理所有重要/必要的任务(此处为GC.SuppressFinalize(this)),并允许派生类仅重写部分代码 这里有两种情况:
Dispose中的SuppressFinalize片段1 Dispose中的代码段2,SuppressFinalize(true) 这里的代码片段1确保始终执行GC.SuppressFinalize。而代码段2则让GC.SuppressFinalize的执行任由派生类的支配 因此,通过将GC.SuppressFinalize放在Dispose方法中,作为类的设计者,您将始终确保无论派生类编写什么代码,都将执行GC.SuppressFinalize
这只是在Dispose中写入SuppressFinalize而不是Dispose(true)的好处。原因。Dispose是指托管代码(您的代码)处理对象,从而选择退出最终确定。人们通常通过最终用户创建另一条进入Dispose(bool disposing)的路由,最终用户的调用没有任何意义。Dispose(bool isDisposing)方法不是接口的一部分 您通常会从方法中调用
Dispose(true)
,并从终结器中调用Dispose(false)
,作为尚未处理对象的回退
调用告诉GC不需要调用对象的终结器,可能是因为所有清理都是在调用Dispose
时完成的
如果类中没有终结器,那么根本不需要调用SuppressFinalize
,因为没有要抑制的终结器
Joe Duffy有一些很好的方法。由于Stackoverflow支持标记,您不应该在邮件标题前面加上[.NET];-)类似的问题-但如果我多次呼吁公众处置(因为根据指导原则,这应该是可能的),那么压制呼吁也会多次呼吁。不应该是这样的。。。在我的代码示例中,它只会被调用一次。尽管Dispose可以被调用多次,但它通常是代码库中其他地方出现问题的征兆——两段或多段代码认为它们控制了对象的生命周期。类似地,可以多次调用GC.SuppressFinalize。虽然在多次调用Dispose时,它可能是代码中的一个缺陷,但应该对它进行防御性编程,以便它能够处理它。多次调用SuppressFinalize不是问题。但这是问题的一个迹象。我的示例是一个具有IDisposable的复杂基类结构。我用IDisposable实现(模板)搜索了许多场景,但没有找到正确的基类->派生类示例。这不是一个完整的示例@MSDN:MSDN只显示基类实现,而不是基类/派生类示例。感谢您提供的信息,但这是主题吗?看看我的具体问题,这是关于抑制调用的位置。你问题中的示例没有终结器,如果你的“真实”代码也是这样,那么无论你在哪里调用抑制终结器都是不相关/不必要的,因为没有要抑制的终结器。@Henk,绝对正确,我应该在回答中说清楚。我想指出的一点是,如果您的类首先没有终结器,那么调用SuppressFinalize的位置是完全不相关的@亨克,不一定。终结器很昂贵。只有在绝对需要时才应该实现终结器,除非类直接处理非托管资源,否则不应该实现终结器。在使用非托管资源时,如果没有使用Dispose()调用,则必须使用终结器来清理非托管内容。当派生类忽略基Dispose调用时,则不会清理更多资源…我认为正确实现基调用是派生类的责任,所以我还是喜欢我的解决方案。@PatrickPeters:如果派生类的资源需要在父类的资源之后进行清理,则在该派生类完成清理之前,不应调用
GC.SuppressFinalize
。将SuppressFinalize
调用放在虚拟方法中会导致其被提前调用。