【转】编写高质量代码改善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个建议》陆敏技

posted @ 2017-12-06 15:34  指间的徘徊  阅读(244)  评论(0编辑  收藏  举报