• 【转】编写高质量代码改善C#程序的157个建议——建议69:应使用finally避免资源泄漏


    建议69:应使用finally避免资源泄漏

    除非发生让应用程序中断的异常,否则finally总是会先于return执行。finally的这个语言特性决定了资源释放的最佳位置就是在finally块中;另外,资源释放会随着调用堆栈由下往上执行。下面的代码验证了这一点,先定义一个需要释放的类:

        class ClassShouldDisposeBase : IDisposable
        {
            string _methodName;
            public ClassShouldDisposeBase(string methodName)
            {
                _methodName = methodName;
            }
            public void Dispose()
            {
                this.Dispose(true);
                GC.SuppressFinalize(this);
                Console.WriteLine("在方法:" + _methodName + "中被释放!");
            }
    
            protected virtual void Dispose(bool disposing)
            {
                if (disposing)
                {
                    //执行基本的清理代码
                }
            }
    
            ~ClassShouldDisposeBase()
            {
                this.Dispose(false);
            }
        }

    再来模拟一个调用堆栈:

            static void Main(string[] args)
            {
                Method1();
            }
    
            static void Method1()
            {
                ClassShouldDisposeBase c = null;
                try
                {
                    c = new ClassShouldDisposeBase("Method1");
                    Method2();
                }
                finally
                {
                    c.Dispose();
                }
    
            }
    
            static void Method2()
            {
                ClassShouldDisposeBase c = null;
                try
                {
                    c = new ClassShouldDisposeBase("Method2");
                }
                finally
                {
                    c.Dispose();
                }
            }

    输出:

    在方法:Method2中被释放!
    在方法:Method1中被释放!

    finally不会因为调用堆栈中存在的异常而被终止,CLR会先执行catch块,然后再执行finally块。如下:

            static void Main(string[] args)
            {
                Method3();
            }
    
            static void Method3()
            {
                ClassShouldDisposeBase c = null;
                try
                {
                    c = new ClassShouldDisposeBase("Method3");
                    Method4();
                }
                catch
                {
                    Console.WriteLine("在Method3中捕获了异常。");
                }
                finally
                {
                    c.Dispose();
                }
    
            }
    
            static void Method4()
            {
                ClassShouldDisposeBase c = null;
                try
                {
                    c = new ClassShouldDisposeBase("Method4");
                    throw new Exception();
                }
                catch
                {
                    Console.WriteLine("在Method4中捕获了异常。");
                    throw;
                }
                finally
                {
                    c.Dispose();
                }
            }

    输出:

    在Method4中捕获了异常。
    在方法:Method4中被释放!
    在Method3中捕获了异常。
    在方法:Method3中被释放!


    转自:《编写高质量代码改善C#程序的157个建议》陆敏技

  • 相关阅读:
    大话计算机网络一 聊聊UDP
    Go调度器系列(2)宏观看调度器
    Go语言高阶:调度器系列(1)起源
    gin+go-micro+etcd实战一
    记录一次云主机部署openstack的血泪史
    paste deploy 学习笔记
    Openstack计算Nova组件
    jumpserver docker简单搭建
    [原创][开源] SunnyUI.Net 帮助文档目录
    [原创][开源]SunnyUI.Net, C# .Net WinForm开源控件库、工具类库、扩展类库、多页面开发框架
  • 原文地址:https://www.cnblogs.com/farmer-y/p/7992968.html
Copyright © 2020-2023  润新知