none
在下面的代码中为何要用析构函数? RRS feed

  • 问题

  • using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace GarbageCollect
    {
      
    publicclass Factory : IDisposable
       {
         
    private StringBuilder sb = new StringBuilder();
          List
    <int> list = new List<int>();

         
    //拼接字符串,创造一些内存垃圾
    publicvoid MakeSomeGarbage()
          {
            
    for (int i = 0; i < 50000; i++)
             {
                sb.Append(i.ToString());
             }
          }

         
    //销毁类时,会调用析构函数
          ~Factory()
          {
             Dispose(
    false);
          }

         
    publicvoid Dispose()
          {
             Dispose(
    true);
          }

         
    protectedvirtualvoid Dispose(bool disposing)
          {
            
    if (!disposing)
             {
               
    return;
             }
             sb
    = null;
             GC.Collect();
             GC.SuppressFinalize(
    this);
          }
       }
    }

         
    2015年4月27日 7:43

答案

  • Hi Meijun,

    首先我觉得析构函数是用来做清理和释放资源的工作的,比如在建立对象时用new开辟了一片内存空间,则应在退出前在析构函数释放。而程序员无法控制何时调用析构函数,因为这是由垃圾回收器决定的。 垃圾回收器检查是否存在应用程序不再使用的对象。 如果垃圾回收器认为某个对象符合析构,则调用析构函数(如果有)并回收用来存储此对象的内存。 程序退出时也会调用析构函数。

    通常,与运行时不进行垃圾回收的开发语言相比,C# 无需太多的内存管理。  这是因为 .NET Framework 垃圾回收器会隐式地管理对象的内存分配和释放。 但是,当应用程序封装窗口、文件和网络连接这类非托管资源时,应当使用析构函数释放这些资源。

    现在看你的这段代码,析构函数中调用Dispose(false)方法,注意false,如果这是个完整的类定义的话,我觉得这个析构函数没多大必要写,因为当垃圾回收器清理完后,没有需要额外手动清理的非托管资源,StringBuilder对象已经被回收了,所以我觉得这个类可以改成这样:

    public class Factory : IDisposable
        {
           private bool IsDisposed = false;  
           private StringBuilder sb = new StringBuilder();
           List<int> list = new List<int>();
           System.IO.StreamReader sr = new System.IO.StreamReader(@"c.a.txt");
    
           //拼接字符串,创造一些内存垃圾
           public void MakeSomeGarbage()
           {
              for (int i = 0; i < 50000; i++)
              {
                 sb.Append(i.ToString());
              }
           }
    
           //销毁类时,会调用析构函数
          ~Factory()
           {
              Dispose(false);
           }
    
           public void Dispose()
           {
              Dispose(true);
           }
    
           protected virtual void Dispose(bool disposing)
           {
              if(!IsDisposed)
              {
                  if (disposing)
                  {
                      sb = null;
                      GC.Collect();
                      GC.SuppressFinalize(this);
                  }
                  sr.Dispose();
                  sr.Close();
              }
              IsDisposed = true;
           }
        }

    这个类改成这样,可能会更容易理解析构函数的作用,当程序执行完时,没有手动调用Dispose()方法,这时垃圾回收器会回收StringBuilder对象,但是StreamReader并没有被释放,这时析构函数会调用Dispose()方法,将StreamReader释放。

    希望我的回答能对你有所帮助。

    Best Regards,
    Xavier Eoro



    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2015年4月28日 8:48