實現IDisposable介面,手動完成資源回收

來源:互聯網
上載者:User

之前nc樓豬一直想當然地認為一個對象實現了IDisposable介面,執行GC.Collect方法後,GC會協助我們自動實現對所有資源的回收。比如下面的一段代碼:
1、一個繼承自IDisposable介面的類

代碼

using System;
using System.IO;

class Sample4GC : IDisposable
{
    private string filePath = string.Empty;

    private FileStream fs;

    public Sample4GC()
    {
        filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "test.txt");
        fs = File.Open(filePath, FileMode.OpenOrCreate);
        //using (fs = File.Open(filePath, FileMode.OpenOrCreate)) //沒有這麼寫是因為樓豬以為GC強制回收就可以了
        //{
        Console.WriteLine("開啟文本了...");
        //}
    }

    /// <summary>
    /// Finalize 解構函式
    /// </summary>
    ~Sample4GC()
    {
        Console.WriteLine("對象被銷毀...");
    }

    public void Dispose()
    {
        GC.Collect();//強制回收
    }
}

 2、測試代碼

代碼

        static void Main(string[] args)
        {
      
            using (Sample4GC sample1 = new Sample4GC())
            {
                 // code to do
            }

            //拋出IOException,提示test.txt正由另一進程使用
            using (Sample4GC sample2 = new Sample4GC())
            {
                 // code to do
            }

            Console.ReadKey();
        }

如您所看到的那樣,nc樓豬自以為通過using這種寫法,就可以高枕無憂地多次執行個體化對象了。可是,在sample2執行個體化執行到建構函式的下面這行:
 fs = File.Open(filePath, FileMode.OpenOrCreate);
竟然拋出了檔案被另一個進程使用無法訪問的異常。
非常奇怪,難道using了之後,sample1還在佔用測試文本資源而沒有被回收?可是樓豬在Dispose方法上加了斷點,GC.Collect()方法明顯執行了一次啊,強制回收了怎麼文本資源還被另一個進程使用呢?
無奈,稍微改了一下建構函式裡的代碼,如下:

代碼

  public Sample4GC()
    {
        filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "test.txt");
        //fs = File.Open(filePath, FileMode.OpenOrCreate);
        using (fs = File.Open(filePath, FileMode.OpenOrCreate)) //這樣就安全了
        {
            Console.WriteLine("開啟文本了...");
        }
    }

果然這次就沒有異常了。可是像上面那樣寫還要繼承IDisposable介面幹什麼呢? 嗯...難道是Dispose方法裡的GC.Collect這玩意沒有回收檔案流對象嗎?
好吧,那就把  using (fs = File.Open(filePath, FileMode.OpenOrCreate)) 這種寫法再改回原來的 fs = File.Open(filePath, FileMode.OpenOrCreate) 這種不安全的寫法,然後再改進Dispose方法試試看:

代碼

   public void Dispose()
    {
        if (fs != null)
        {
            //fs.Close();//關閉 
            fs.Dispose();//檔案流回收 不管Close還是Dispose 都實現了回收
        }
        GC.Collect();//強制回收
    }

我kao,果然正常,而且不管是執行檔案流的Close還是Dispose方法,都實現了資源的回收,樓豬不禁一陣激動。

到這裡,樓豬可以確定,果然是樓豬自己誤解了GC.Collect方法,沒有正確實現好Dispose方法。最後模仿msdn優雅的寫法,改進一下實現代碼:

代碼

 class Sample4GC : IDisposable
    {
        private bool isDisposed = false;

        private string filePath = string.Empty;

        private FileStream fs;

        public Sample4GC()
        {
            filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "test.txt");
            fs = File.Open(filePath, FileMode.OpenOrCreate);
            //using (fs = File.Open(filePath, FileMode.OpenOrCreate))
            //{
            Console.WriteLine("開啟文本了...");
            //}
        }

        /// <summary>
        /// Finalize 解構函式
        /// </summary>
        ~Sample4GC()
        {
            Console.WriteLine("對象被銷毀...");
            Dispose(false);
        }

        public void Dispose()
        {
            Console.WriteLine("手動銷毀對象...");
            GC.SuppressFinalize(this); //通知GC:對象已經被銷毀過,不用GC處理了
              Dispose(true);
        }

        /// <summary>
        /// 自己實現的對象回收主方法
        /// </summary>
        /// <param name="isDisposing"></param>
        private void Dispose(bool isDisposing)
        {
            if (!isDisposed)
            {
                if (isDisposing)
                {
                    if (fs != null)//手動銷毀FileStream對象
                    {
                        //fs.Close();
                        fs.Dispose();
                    }
                }
            }
            isDisposed = true;
        }

    }

在調用的時候,我們可以顯式調用Dispose方法或者通過using這種寫法自動回收資源:

      Sample4GC sample = new Sample4GC();
      sample.Dispose();//對象回收 

      using (Sample4GC sample2 = new Sample4GC())
      {
            // code to do
      }

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.