我有 DisposableObject 是 IDisposable。我知道它应该被包装到 using 或 dispose 被显式调用。
public void Method()
{
var disposable = new DisposableObject();
}
但我曾与一些同事争论过这个逻辑。您认为 GC 会在某些时候自动调用“未处理”的 Dispose 方法吗?
感谢你的回答。
我有 DisposableObject 是 IDisposable。我知道它应该被包装到 using 或 dispose 被显式调用。
public void Method()
{
var disposable = new DisposableObject();
}
但我曾与一些同事争论过这个逻辑。您认为 GC 会在某些时候自动调用“未处理”的 Dispose 方法吗?
感谢你的回答。
在这种情况下,GC 会自动调用 Dispose 方法吗?
不,它不会调用Dispose
你必须自己调用它或使用using
块,即使在出现异常的情况下也能确保它的处置。
using(var disposable = new DisposableObject())
{
//your code
}
IDisposable
用于确保应用程序持有的非托管资源在垃圾回收之前被释放。由于GC
无法释放文件处理程序等非托管资源持有的资源。
不,GC 不会对一次性对象(实现 IDisposable 的对象)调用 Dispose。GC 通过调用托管对象的终结器(析构函数)来管理对象清理。如果您想控制何时释放管理资源(而不是是否释放它们),您可以实现 Dispose 方法。
例如,如果您有一个具有 TCPClient 成员的类,那么这是一个控制资源的托管对象 - 它连接的端口。如果你没有在你的类上实现 IDispose 并且你使用了一个实例,那么当 GC 看到 TCPClient 不再被使用时,它将最终确定该对象并且端口将关闭 - 但你无法控制 WHEN 这将发生。如果您需要访问端口和特定时间,那么您需要在其关闭时进行控制 - 在这种情况下,您可以实现 IDispose 并使用 using 语句或自己直接调用 Dispose 以确保释放资源(端口)。
如果一个类重写了一个调用的方法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
调用它。