0

我有 DisposableObject 是 IDisposable。我知道它应该被包装到 using 或 dispose 被显式调用。

public void Method()    
{
       var disposable = new DisposableObject();
}

但我曾与一些同事争论过这个逻辑。您认为 GC 会在某些时候自动调用“未处理”的 Dispose 方法吗?

感谢你的回答。

4

3 回答 3

3

在这种情况下,GC 会自动调用 Dispose 方法吗?

,它不会调用Dispose你必须自己调用它或使用using块,即使在出现异常的情况下也能确保它的处置。

using(var disposable = new DisposableObject())
{
  //your code
}

IDisposable用于确保应用程序持有的非托管资源在垃圾回收之前被释放。由于GC无法释放文件处理程序等非托管资源持有的资源。

于 2013-10-22T13:03:27.630 回答
1

不,GC 不会对一次性对象(实现 IDisposable 的对象)调用 Dispose。GC 通过调用托管对象的终结器(析构函数)来管理对象清理。如果您想控制何时释放管理资源(而不是是否释放它们),您可以实现 Dispose 方法。

例如,如果您有一个具有 TCPClient 成员的类,那么这是一个控制资源的托管对象 - 它连接的端口。如果你没有在你的类上实现 IDispose 并且你使用了一个实例,那么当 GC 看到 TCPClient 不再被使用时,它将最终确定该对象并且端口将关闭 - 但你无法控制 WHEN 这将发生。如果您需要访问端口和特定时间,那么您需要在其关闭时进行控制 - 在这种情况下,您可以实现 IDispose 并使用 using 语句或自己直接调用 Dispose 以确保释放资源(端口)。

于 2013-10-22T14:14:02.610 回答
1

如果一个类重写了一个调用的方法Finalize,并且发现该类的一个实例已被放弃而没有GC.SuppressFinalize()在该实例上被调用,则 GC 将对该对象的引用存储在Finalize应尽快运行的事物列表中(暂时恢复它) 并标记对象,以便下次丢弃它时它会简单地消失。如果任何对象已被放置在列表中以立即完成,则 GC 将启动一个线程来运行它们的Finalize方法。

无论出于何种原因,C# 的创建者决定通过禁止程序员Finalize直接覆盖,而是要求希望覆盖的程序员Finalize使用他们称为“析构函数”的构造,其语法让人联想到 C++ 析构函数,但完全不同语义。尽管 C# 添加了一些包装代码,但通常可以认为~className {whatever}大致相当于覆盖Finalize.

Microsoft 建议,如果覆盖Finalize(或实现 C# 析构函数),则该覆盖/析构函数应简单地调用带有签名的方法void Dispose(bool),并传递False参数值。它基于该建议,人们得到了 GC 调用的想法Dispose。请注意,GC本身不会调用Dispose; 进一步注意,大多数对象不应实现 C# 析构函数,也不应Finalize以任何其他方式覆盖。除非了解所有与 相关的极端情况Finalize,否则通常最好确保在放弃对象之前IDisposable.Dispose调用它。

于 2013-10-22T15:31:29.593 回答