C#:实现IDisposable接口时Dispose方法的内容应该是什么

时间:2011-02-18 13:58:11

标签: c# inheritance interface implementation idisposable

我创建了一个实现 IDisposable 接口的类,VisualStudio IDE为我带来了Dispose方法。我想知道我应该在Dispose方法中编写什么代码,以便它将负责我的内存管理或它应该做的任何事情。

public class ESNVerification : IDisposable 
{ 

  public bool Save(string a,string b)
  {
    //Save the data to table
    return true;
  }

  public void Dispose()
  {
       throw new NotImplementedException();
       // Really what i should do here  ?
  }
}

9 个答案:

答案 0 :(得分:3)

我建议Three Simple Rules了解如何实现IDisposable;简化到这里:

  • 规则1:不要这样做(除非你需要)。只有两种情况需要实现IDisposable该类拥有非托管资源该类拥有托管(IDisposable)资源
  • 规则2:对于拥有托管资源的类,请实施IDisposable(但不是终结器)。 IDisposable的此实现应仅为每个拥有的资源调用Dispose。这堂课不应该有终结者。
  • 规则3:对于拥有单个非托管资源的类,请同时实现IDisposable和终结器。

答案 1 :(得分:2)

除非你正在使用某些需要清理的非托管资源(在这个非常简单的情况下,你不是这样),那么你真的没有理由实现IDisposable

IDisposable接口的MSDN描述中的第一行:

  

此界面的主要用途是   释放非托管资源

如果您使用的是非托管资源,则可以使用Dispose方法确保正确发布这些资源(垃圾收集器将为您处理所有托管资源)。

答案 2 :(得分:1)

Dispose意在释放非托管资源(即使用后垃圾收集器不会自动处理的资源)。常见示例是数据库和文件连接。 Implementing a Dispose Method提供了更多解释和代码示例。

该页面有一个重要警告,即Dispose方法应该以多次调用不会引发异常的方式实现。那是因为它被垃圾收集器使用,它可以多次调用dispose方法。

答案 3 :(得分:1)

答案 4 :(得分:1)

在99%的案例中,微软的框架过于复杂,而且正确的方法很简单:

  1. 如果您的类具有实现IDisposable的任何类型的字段,并且在完成它们之后没有人希望使用这些对象,那么您应该实现IDisposable,并且您的处理方法应该在所有这些字段上调用Dispose。
  2. 如果你的类没有这样的字段,但你认为派生自你的类可能,或者你的类需要实现像IEnumerator(of T)这样需要IDisposable的接口,你应该有一个可覆盖的Dispose什么都不做的方法。
  3. “dispose”方法的正确语义是对象在放弃之前清除其他对象所做的任何事情。如果一个对象不必清理其他对象,Dispose应该无害地做任何事情。永远不会有任何理由从Dispose中抛出NotImplementedException或NotSupportedException。

实现IDisposable的关键点不是清理任何特定类型的“资源”,而是确保如果对象以需要的方式更改系统中的其他实体在某些时候被清理,这些实体将被清理,而这样做的信息和动力仍然存在。理想情况下,这种清理应该尽快发生,但不久就会发生。如果对象包含例如除了一堆字符串数组外,没有必要进行清理。字符串不需要任何清理;不需要清理的对象数组不需要任何清理,除了不需要清理的其他对象之外什么也不需要清理的对象也不需要清理。另一方面,打开TCP套接字等操作需要确保执行某些清理操作(关闭套接字)。如果一个对象打开一个TCP套接字并保留有关它的信息,那么在该对象上调用Dispose的目的不是要销毁有关套接字的信息(将由垃圾收集器处理),而是确保必要的执行TCP堆栈上的“关闭”操作。

答案 5 :(得分:0)

MSDN上有两篇相当不错的文章:Implementing a Dispose MethodImplementing Finalize and Dispose to Clean Up Unmanaged Resources。观察到第一个说:

  

在仅使用托管资源(例如数组)的类型上实现Dispose方法没有性能优势,因为它们会被垃圾回收器自动回收。

我建议你阅读两者,决定是否需要实现它,并在那里使用代码示例作为开始。

答案 6 :(得分:0)

dispose方法在那里,您可以释放已分配的非简单对象(通过垃圾回收清理)的任何资源。例如

  • 数据库连接和/或结果集
  • 指向非托管对象的指针
  • 您在对象中分配的任何对象,也是在实现IDisposable
应该在Dispose方法中清理

(可能通过调用这些对象上的Dispose)。

如果您没有任何此类资源,则可能不需要实现IDisposable。但是,您可能正在实现从IDisposable继承的另一个接口,例如IEnumerator。在这种情况下,如果您没有上述任何资源,则可以将Dispose方法留空。

答案 7 :(得分:0)

实施IDisposable 1 只有两个理由,你在Dispose方法中所做的取决于哪一个适用于你的情况。

如果您的类创建了实现IDisposable的对象实例,并且无法在创建它们的方法中处置它们,那么该类将具有引用这些实例的成员变量。该课程还应该实现IDisposable,在其中你应该在每个一次性成员上调用Dispose

如果您直接使用非托管资源,那么您的类应该实现IDisposable,并且在Dispose方法中,您应该根据需要处理它们。究竟是什么意思会有很大不同,因为没有可用的标准界面。这非常不常见 - 通常您使用托管类来处理这些问题,例如FileStreamSqlConnection。 (在这种情况下,见上文。)

1 除非你是deliberately using IDisposable in a non-standard way。 (虽然are debatable的优点。)

答案 8 :(得分:-1)

当您的类使用非托管系统资源时,应使用IDisposable模式,作为文件句柄,指针...释放他们使用的内存。

如果您的类不使用非托管资源,则可能不需要使用此模式。

如果你真的需要IDisposable:

public void Dispose()
{
  //Free here your resources

  this.Dispose(true);
  GC.SuppressFinalize(this);
}