在C#中使用Finalize / Dispose方法 [英] Use of Finalize/Dispose method in C#

查看:112
本文介绍了在C#中使用Finalize / Dispose方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C#2008

我已经花了一段时间了,但我仍然对在代码中使用finalize和dispose方法感到困惑。我的问题如下:

I have been working on this for a while now, and I am still confused about the use of finalize and dispose methods in code. My questions are below:


  1. 我知道我们只需要一个终结器即可处理非托管资源。但是,如果有托管资源可以调用非托管资源,那么它仍然需要实现终结器吗?

  1. I know that we only need a finalizer while disposing unmanaged resources. However, if there are managed resources that make calls to unmanaged resources, would it still need to implement a finalizer?

但是,如果我开发的类不不使用任何非托管资源-直接还是间接使用,我应该实现 IDisposable 来允许该类的客户端使用 using语句吗?

However, if I develop a class that doesn't use any unmanaged resource - directly or indirectly, should I implement the IDisposable to allow the clients of that class to use the 'using statement'?

仅仅为了使您的类的客户能够使用using语句实现IDisposable可行吗?

Would it be feasible to implement IDisposable just to enable clients of your class to use the using statement?

using(myClass objClass = new myClass())
{
    // Do stuff here
}


  • 我在下面开发了这个简单的代码来演示Finalize / dispose的使用:

  • I have developed this simple code below to demonstrate the Finalize/dispose use:

    public class NoGateway : IDisposable
    {
        private WebClient wc = null;
    
        public NoGateway()
        {
            wc = new WebClient();
            wc.DownloadStringCompleted += wc_DownloadStringCompleted;
        }
    
    
        // Start the Async call to find if NoGateway is true or false
        public void NoGatewayStatus()
        {
            // Start the Async's download
                // Do other work here
            wc.DownloadStringAsync(new Uri(www.xxxx.xxx));
        }
    
        private void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            // Do work here
        }
    
        // Dispose of the NoGateway object
        public void Dispose()
        {
            wc.DownloadStringCompleted -= wc_DownloadStringCompleted;
            wc.Dispose();
            GC.SuppressFinalize(this);
        }
    }
    


  • 有关源代码的问题:


    1. 在这里,我没有添加终结器,通常,终结器将由GC调用,终结器将调用Dispose。由于没有终结器,我什么时候调用Dispose方法?

    1. Here I have not added the finalizer, and normally the finalizer will be called by the GC, and the finalizer will call the Dispose. As I don't have the finalizer, when do I call the Dispose method? Is it the client of the class that has to call it?

    所以在示例中,我的类称为NoGateway,客户端可以使用和处置这样的类:

    So my class in the example is called NoGateway and the client could use and dispose of the class like this:

    using(NoGateway objNoGateway = new NoGateway())
    {
        // Do stuff here   
    }
    

    当执行到达using块的末尾时,是否会自动调用Dispose方法?客户端是否必须手动调用dispose方法?即

    Would the Dispose method be automatically called when execution reaches the end of the using block, or does the client have to manually call the dispose method? i.e.

    NoGateway objNoGateway = new NoGateway();
    // Do stuff with object
    objNoGateway.Dispose(); // finished with it
    


  • 我正在使用 WebClient NoGateway 类中的code>类。因为 WebClient 实现了 IDisposable 接口,这是否意味着 WebClient 间接使用非托管资源?有严格的规则可以遵循吗?我怎么知道一个类使用非托管资源?

  • I am using the WebClient class in my NoGateway class. Because WebClient implements the IDisposable interface, does this mean that WebClient indirectly uses unmanaged resources? Is there a hard and fast rule to follow this? How do I know that a class uses unmanaged resources?


    推荐答案

    推荐IDisposable模式位于此处。编程使用IDisposable的类时,通常应使用两种模式:

    The recommended IDisposable pattern is here. When programming a class that uses IDisposable, generally you should use two patterns:

    当实现不使用非托管资源的密封类时,只需将Dispose方法实现为具有常规接口实现:

    When implementing a sealed class that doesn't use unmanaged resources, you simply implement a Dispose method as with normal interface implementations:

    public sealed class A : IDisposable
    {
        public void Dispose()
        {
            // get rid of managed resources, call Dispose on member variables...
        }
    }
    

    实现未密封的类时,请按以下步骤操作:

    When implementing an unsealed class, do it like this:

    public class B : IDisposable
    {    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // get rid of managed resources
            }   
            // get rid of unmanaged resources
        }
    
        // only if you use unmanaged resources directly in B
        //~B()
        //{
        //    Dispose(false);
        //}
    }
    

    请注意,我尚未声明终结器在 B 中;仅当您有要处理的实际非托管资源时,才应实现终结器。即使调用了 SuppressFinalize ,CLR处理可终结对象的方式也不同于不可终结对象。

    Notice that I haven't declared a finalizer in B; you should only implement a finalizer if you have actual unmanaged resources to dispose. The CLR deals with finalizable objects differently to non-finalizable objects, even if SuppressFinalize is called.

    除非必须这样做,否则不应该声明终结器,但是您可以给类的继承者一个钩子,以调用 Dispose 并在它们直接使用不受管资源的情况下自己实现终结器: / p>

    So, you shouldn't declare a finalizer unless you have to, but you give inheritors of your class a hook to call your Dispose and implement a finalizer themselves if they use unmanaged resources directly:

    public class C : B
    {
        private IntPtr m_Handle;
    
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // get rid of managed resources
            }
            ReleaseHandle(m_Handle);
    
            base.Dispose(disposing);
        }
    
        ~C() {
            Dispose(false);
        }
    }
    

    如果您不直接使用非托管资源( SafeHandle 和朋友不算在内,因为他们声明了自己的终结器),那么就不要实现终结器,因为GC处理终结类的方式有所不同,即使您以后取消终结器。还要注意,即使 B 没有终结器,它仍会调用 SuppressFinalize 正确处理任何子类。确实实现了终结器。

    If you're not using unmanaged resources directly (SafeHandle and friends doesn't count, as they declare their own finalizers), then don't implement a finalizer, as the GC deals with finalizable classes differently, even if you later suppress the finalizer. Also note that, even though B doesn't have a finalizer, it still calls SuppressFinalize to correctly deal with any subclasses that do implement a finalizer.

    当类实现IDisposable接口时,这意味着在某些地方,当您完成使用后应该摆脱一些非托管资源。班级。实际资源封装在类中;您无需明确删除它们。只需调用 Dispose()或将类包装在 using(...){} 中,即可确保任何不受管理的资源会根据需要删除。

    When a class implements the IDisposable interface, it means that somewhere there are some unmanaged resources that should be got rid of when you've finished using the class. The actual resources are encapsulated within the classes; you don't need to explicitly delete them. Simply calling Dispose() or wrapping the class in a using(...) {} will make sure any unmanaged resources are got rid of as necessary.

    这篇关于在C#中使用Finalize / Dispose方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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