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

查看:22
本文介绍了在 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 以允许该类的客户端使用使用陈述'?

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'?

实现 IDisposable 只是为了让你的类的客户能够使用 using 语句是否可行?

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. 这里我没有添加finalizer,一般情况下finalizer会被GC调用,finalizer会调用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
    

  • 我在我的 NoGateway 类中使用 WebClient 类.因为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 并自己实现终结器:

    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天全站免登陆