【问题标题】:Do I need to implement a dispose or finalize in my objects?我需要在我的对象中实现 dispose 或 finalize 吗?
【发布时间】:2011-03-31 10:40:24
【问题描述】:

长期以来,我让垃圾收集器发挥作用,从我自己身上卸下所有责任。

遗憾的是它从来没有变成一个问题......所以我从来没有考虑过这个主题。

现在回想起来,我真的不明白“dispose”函数的真正作用以及应该如何以及何时实现它。

finalize 同样的问题...

最后一个问题... 我有一个类pictureManipulation:当我需要保存/调整大小/更改格式时...我启动该类的一个新实例,使用它的对象并且...让垃圾收集杀死实例

class student
{
   public void displayStudentPic()
   {
      PictureManipulation pm = new PictureManipulation();
      this.studentPic = pm.loadStudentImage(id); 
   }
}

Class Test
{
  student a = new Student();
  a.displayStudentPic();
  // Now the function execution is ended... does the pm object is dead? Will the GC will kill it?
}

【问题讨论】:

标签: c# dispose garbage-collection finalize


【解决方案1】:

关于你的class Student

我需要Dispose() 吗?

假设 Picture 类是 IDisposable:。因为 Student 对象“拥有”studentPic,这使得它负责清理它。一个最小的实现:

class Student : IDisposable
{
   private PictureClass studentPic;
   public void Dispose()
   {
      if (studentPic != null)
        studentPic.Dispose();
   }
   ...
}

您现在使用 Student 对象,例如:

void Test
{
  using (Student a = new Student())
  {
     a.displayStudentPic();    
  } // auto Dispose by using() 
}

如果您不能/不使用 using(){} 块,只需在完成后调用 a.Dispose();

但请注意,这里(远)更好的设计是避免在 Student 对象中保留图片对象。这引发了整个责任链。

我需要终结器吗?

。因为当一个 Student 对象被收集时,它的 studentPic 对象保证在同一次运行中被收集。终结器(析构函数)将毫无意义,但仍然很昂贵。

【讨论】:

  • 很好的答案,有助于迈出理解的第一步......理论非常重要,但我总是觉得第一步最难:)
【解决方案2】:

仅当您的类型拥有一些非托管资源(如数据库连接、文件句柄等)或您的类型拥有的某些对象实现了 IDisposable 接口时,您才需要实现 Dispose 方法。以下是您在实施标准 Dispose 模式时应考虑的几点:

  • 如果您的对象不包含任何 IDisposable 对象或非托管资源(例如 DB 连接),那么您根本不需要实现 IDisposable 或终结器
  • 如果您的对象包含对 IDisposable 对象的引用,则在 Dispose 方法中对这些对象调用 Dispose()
  • 如果您的对象不包含任何非托管资源,则不要实现终结器,除非您已实现终结器,否则垃圾收集器将不会尝试终结您的对象(这会影响性能)。
  • 如果您的对象包含非托管资源,请在终结器中清理它们,而无需在 Dispose(bool) 方法中重新编写任何清理代码。

【讨论】:

  • +1: @Asaf: "Managed Resources" = 任何没有文件、数据库或存在于您正在运行的程序之外的其他“事物”。
  • @Binary:我认为 Managed-resource == 确实对某事有(间接)句柄。
  • @Henk:“托管资源”=垃圾收集器担心的事情。没有?
  • @Binary,我的最佳理解:托管资源 == 间接/嵌套非托管资源。此答案中的要点 2。
  • @Henk:看来我是少数派,似乎没有“托管资源”的明确定义,但有意识的似乎遵循您的定义。先生,我是正确的:)
【解决方案3】:

如果对象持有的资源不仅仅是对象本身持有的内存,则需要注意对象处置。

例如,如果你的对象抽象了一个文件,你必须控制文件何时被释放,否则你会搞砸非常糟糕的事情:你的应用程序使用完它仍然会被锁定,直到 GC 处理你的对象。

要了解如何正确执行此操作,请阅读有关 dispose 和 finalize 以及 using(){} 子句的手册。

【讨论】:

    猜你喜欢
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 2014-10-07
    • 1970-01-01
    • 2018-03-23
    • 2019-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多