当我们没有析构函数时,为什么我们应该调用SuppressFinalize [英] Why should we call SuppressFinalize when we don't have a destructor

查看:123
本文介绍了当我们没有析构函数时,为什么我们应该调用SuppressFinalize的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



1)为什么我们不应该在Dispose函数中调用SuppressFinalize有一个析构函数。

2)Dispose和finalize用于在垃圾收集对象之前释放资源。无论是托管资源还是非托管资源,我们需要释放它,那么为什么我们需要在dispose函数内部存在一个条件,当我们从IDisposable调用该重写函数时传递'true':Dispose并在从finalize调用时传递false。



查看下面我从网上复制的代码。

  class Test:IDisposable 
{
private bool isDisposed = false;

〜Test()
{
Dispose(false);
}

保护无效Dispose(bool处置)
{
如果(处置)
{
//处理受管资源的代码
}
//处理类的未管理资源的代码

isDisposed = true;
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);




$ b $ p
$ b

如果我删除布尔型保护的Dispose函数并执行

  class Test:IDisposable 
{
private bool isDisposed = false;

〜Test()
{
Dispose();
}


public void Dispose()
{
//用于处理类的受管资源的代码
//代码处理类的未管理资源
isDisposed = true;

//因为我们有一个析构函数,所以请调用它。如果我们没有一个
GC.SuppressFinalize(this),该怎么办?
}
}


解决方案

I在这里肢体会出去,但是......大多数人不需要全面的处置模式。它被设计成在直接访问非托管资源(通常通过 IntPtr )和面对继承时是坚实的。大多数情况下,这些都不是必需的。



如果您只是持有对其他实现 IDisposable ,你几乎肯定不需要终结器 - 无论是直接持有资源负责处理。你可以做这样的事情:

  public sealed class Foo:IDisposable 
{
private bool布置;
私有FileStream流;
$ b $ //其他代码

public void Dispose()
{
if(disposed)
{
return;
}
stream.Dispose();
disposed = true;


请注意,不是 em>线程安全的,但这可能不会成为问题。



通过不必担心子类直接持有资源的可能性,您不需要以抑制终结者(因为没有一个) - 而且你不需要提供一种定制处置的子类方法。



如果你的 do 需要允许不受控制的继承(也就是说你不愿意打赌子类会有很强的继承)请注意,使用.NET 2.0中的 SafeHandle ,您需要使用完整模式。

更重要的是,你需要自己的终结器,而不是.NET 1.1中的。






为了解决你为什么有这样的观点首先放置标志:如果您在终结器中运行,您引用的其他对象可能已经完成。你应该让他们自己清理,而且你应该直接清理你自己的资源。


I have few Question for which I am not able to get a proper answer .

1) Why should we call SuppressFinalize in the Dispose function when we don't have a destructor .

2) Dispose and finalize are used for freeing resources before the object is garbage collected. Whether it is managed or unmanaged resource we need to free it , then why we need a condition inside the dispose function , saying pass 'true' when we call this overridden function from IDisposable:Dispose and pass false when called from a finalize.

See the below code I copied from net.

class Test : IDisposable
   {
     private bool isDisposed = false;

     ~Test()
     {
       Dispose(false);
     }

     protected void Dispose(bool disposing)
     {
       if (disposing)
       {
         // Code to dispose the managed resources of the class
       }
       // Code to dispose the un-managed resources of the class

       isDisposed = true;
     }

     public void Dispose()
     {
       Dispose(true);
       GC.SuppressFinalize(this);
     }
   }

what if I remove the boolean protected Dispose function and implement the as below.

   class Test : IDisposable
   {
     private bool isDisposed = false;

     ~Test()
     {
       Dispose();
     }


     public void Dispose()
     {
      // Code to dispose the managed resources of the class
      // Code to dispose the un-managed resources of the class
      isDisposed = true;

      // Call this since we have a destructor . what if , if we don't have one 
       GC.SuppressFinalize(this);
     }
   }       

解决方案

I'm going out on a limb here, but... most people don't need the full-blown dispose pattern. It's designed to be solid in the face of having direct access to unmanaged resources (usually via IntPtr) and in the face of inheritance. Most of the time, neither of these is actually required.

If you're just holding a reference to something else which implements IDisposable, you almost certainly don't need a finalizer - whatever holds the resource directly is responsible for dealing with that. You can make do with something like this:

public sealed class Foo : IDisposable
{
    private bool disposed;
    private FileStream stream;

    // Other code

    public void Dispose()
    {
        if (disposed)
        {
            return;
        }
        stream.Dispose();
        disposed = true;
    }
}

Note that this isn't thread-safe, but that probably won't be a problem.

By not having to worry about the possibility of subclasses holding resources directly, you don't need to suppress the finalizer (because there isn't one) - and you don't need to provide a way of subclasses customising the disposal either. Life is simpler without inheritance.

If you do need to allow uncontrolled inheritance (i.e. you're not willing to bet that subclasses will have very particular needs) then you need to go for the full pattern.

Note that with SafeHandle from .NET 2.0, it's even rarer that you need your own finalizer than it was in .NET 1.1.


To address your point about why there's a disposing flag in the first place: if you're running within a finalizer, other objects you refer to may already have been finalized. You should let them clean up themselves, and you should only clean up the resources you directly own.

这篇关于当我们没有析构函数时,为什么我们应该调用SuppressFinalize的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆