using和回收资源

在之前我看的写出优雅简明代码的论题集 -- Csharp(C#)篇[1]后续的评论中,看到了这么个结论:

“这点是却实,using如果出现异常不回收资源,使用using特别要注意这个问题”

其实上面的群论很清晰,using会展成一个try-finally,会在finally里显示调用object的Dispose()方法。

在这我想问的是:你既然都知道会展成什么,他凭什么就不会回收资源呢?难道不知道没有实现IDisposable的事不能using的吗?

先从msdn上捞了一段IDisposable的模板,改了改代码,原来的太复杂,为了凸出重点,我酌情给了删减:

using System;

public class DisposeExample
{
    public class MyResource : IDisposable
    {
        private bool disposed = false;

        // The class constructor.
        public MyResource(){}

        public void ThrowException()
        {
             throw new Exception("Expected exception.");
        }
   
        public void Dispose()
        {
            Dispose(true);
           
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            Console.WriteLine("Dispose.");
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                if (disposing)
                {
                       //WILL DIPOSE RESOURE HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                }

                disposed = true;
            }
        }

        ~MyResource()
        {
            Dispose(false);
        }
    }
    public static void Main()
    {
        using (MyResource my = new MyResource())
        {
            my.ThrowException();
        }
    }
}

这个代码不难读懂吧,在Main里,new了一个对象,让后再using里,call ThrowException()显式的抛出异常,关键是Dispose()方法会不会被调用呢?就是控制台能否打印出Dispose呢?

答案是肯定的。

结论:实现IDisposable接口是为了显式的(因为Finalize()不能显式的来call)确定的(Finalize()调用的不确定性)释放资源。将释放资源的操作放在Dispose()方法里完成,并且通过using来确保调用。至于dctor里Dispose(false)是因为我们不想让GC来释放资源,并且在Dispose()方法调用之后,不让GC去调用Finalize()(GC.SuppressFinalize(this);)。

PLUS:如果在new 对象的过程中发生了异常,则Dispose()方法是无法调用的。可以在ctor里调用ThrowException()试一下。

posted @ 2011-02-22 19:14  DiggingDeeply  阅读(999)  评论(4编辑  收藏  举报