在IDisposable对象数组中Dispose()或不Dispose()元素?

时间:2015-04-07 17:54:13

标签: c# .net vb.net idisposable

从.NET中的函数返回的有很多IDsposable对象的数组或列表示例。例如,Process.GetProcesses()

  • 如果我调用那个方法,那么当我迭代它时,我的责任是Dispose()所有数组成员吗?
  • 为什么它应该是我的责任,因为我从来没有创建过对象,我给出的数组只是指向在我的代码之外创建的对象的指针。

我一直认为这是Dispose()的创造者的负担。 那么这里适当的规则是什么?

4 个答案:

答案 0 :(得分:7)

没有一般规则。它将取决于具体情况,以及如何设计相关方法,以确定“你”是否负责处理您有权访问的对象。这就是文档通常对于帮助该类型用户了解其职责的重要性。

  

我一直以为这是Dispose()

的创造者的负担

这不可能是严格的。有时候,一次性对象会超出创建它的代码块的生命周期。当创建者可以处理对象时最简单,有时它们根本不可能。从方法返回一次性对象时,一种情况是创建一次性对象的代码通常无法清理它,因为它的生命周期需要小于一次性对象的生命周期

答案 1 :(得分:1)

除了相对较少的例外(其中大多数可以被描述为处理设计不佳的代码无法改变的最少邪恶方法),每个IDisposable实例应该在任何给定的时刻有一个明确定义的所有者。如果一个方法返回一个实现IDisposable类型的东西,该方法的契约将指定该方法是否放弃所有权(在这种情况下,调用者应确保该对象被处置 - 通过处置对象本身或将所有权放弃给其他人),或者该方法是否只是返回对其他人拥有的对象的引用

在正确编写的代码中,是否应该处理对象的问题很少是判断调用。物体的所有者应确保其被处置;没有其他人应该处理它。有时可能需要让方法接受一个参数,指示该方法是否应该转移IDisposable的所有权。例如,如果代码想要创建声音,将其传递给“开始播放声音”方法,并且永远不想再次处理该声音,那么让代码播放声音接受并最优化处理完成后发出声音;但是,如果代码想要能够重复播放声音,并确保声音对象只要需要就能保持活着,那么声音播放代码会更方便取得所有权。使用单独的方法可能在某些方面更清晰,但使用参数可以帮助封装。

通常,当代码返回实现IDisposable的对象列表时,代码的目的是识别对象,而不传达对它们的任何所有者权益。如果没有所有权权益,接收此类列表的代码应该在其上调用Dispose

答案 2 :(得分:1)

GetProcesses方法不会在返回的Process实例内分配任何句柄(或其他非托管资源)。

仅当您在返回的Process实例上调用某些方法时,才创建句柄,几乎在所有情况下,这些方法都在返回之前释放(例如Process.Kill)。

因此,在大多数情况下,完全没有必要处置返回的每个Process实例。

答案 3 :(得分:0)

规则很简单:如果您认为其他程序将使用您的IDisposables,那么请不要销毁它们。否则,就这样做。

例如:GetProcesses()返回其他程序可能使用的其他进程,因此您不应该处置

另一方面,您打开的文件应该针对操作系统中的其他进程发布,因此您应该关闭并在其上方处置包装流(例如,您应该处置由{返回的>> {1}}方法)。

<强>更新
From MSDN

  
      
  • DO 在包含的类型上实现Basic Dispose Pattern   一次性类型的实例。请参阅基本处理模式部分   有关基本模式的详细信息。如果一个类型负责   其他一次性物品的使用寿命,开发人员需要一种处理方式   他们也是。使用容器的Dispose方法是一种方便的方法   使这成为可能。
      
        
    • DO 实现基本处理模式   并提供持有资源的类型的终结器   明确释放,没有终结者   例如,应该在存储非托管内存缓冲区的类型上实现该模式。 “可终结类型”部分讨论了与之相关的指南   实施终结者。
    •   
    • CONSIDER 在类本身上实现基本处理模式,这些类本身不包含非托管资源或一次性对象,但可能有子类型。
    •   
  •