c#-具有终结器的开销-在处理中有/没有SuppressFinalize
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c#-具有终结器的开销-在处理中有/没有SuppressFinalize,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2407字,纯文字阅读大概需要4分钟。
内容图文
假设以下内容:
>班级仅管理成员.
>一些成员实现IDisposable.
>类是密封的-类不能从非派生资源派生和添加.
>该对象在using语句内使用-即完成后调用Dispose().
此类有3种可能的IDisposable实现:
>在IDisposable成员上调用Dispose()的最小Dispose方法-没有终结器.
>使用Finalizer BUT的标准IDisposable实现缺少常规的GC.SuppressFinalize(this)调用Dispose().
>使用Finalizer(以及Dispose()中的GC.SuppressFinalize(this)调用)的完整标准IDisposable实现.
以下陈述正确吗?我理解正确吗?
>案例A.的开销比B.和C.少,因为该对象没有终结器,因此它不会进入GC的终结队列中-因为GC可以在收集早期清理该对象-没有开销.
>案例B.该对象具有终结器,因此最终将进入GC终结器队列,并且终结器将被调用(因为未抑制该终结器)-终结器调用dispose不会执行任何操作,因为已被调用.这将导致对象处于终结器队列中的开销很小,并且终结器调用的开销也很小.
>案例C.该对象具有终结器,因此仍将最终出现在GC终结器队列中.因为dispose和SuppressFinalize已被调用,所以终结器不会运行.这种情况仍然会导致终结器队列中的对象开销很小,但是终结器实际上并没有运行.
这里的关键点是,很容易想到“我已经通过调用SuppressFinalize避免了终结器的开销”,但我认为(并想澄清)这是不正确的.终结器队列中仍存在对象的开销-您要避免的是实际的终结器调用-在通常情况下,这只是“我已经无所事事”.
注意:这里的“完全标准IDisposable实现”是指旨在涵盖非托管和托管资源情况的标准实现(请注意,这里我们只有托管对象成员).
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
private bool _disposed;
protected virtual void Dispose(bool disposing) {
if (_disposed)
return;
if (disposing) {
// dispose managed members...
}
_disposed = true;
}
~AXCProcessingInputs() {
Dispose(false);
}
解决方法:
.NET GC的不同版本可能会执行不同的操作,但是据我了解,具有Finalize方法的任何对象都将添加到“ finalizer队列”(如果被放弃则请求通知的对象列表),并将其保留在该队列中只要它存在.注销和重新注册终结的方法(IMHO应该是对象的受保护成员)设置或清除对象标头中的标志,该标志控制对象是否应移至“可到达队列”(其finalize方法应包含对象的列表)如果发现已放弃该对象,则将尽快运行),但不会导致该对象被添加到终结器队列中或从中删除.
因此,覆盖类型的每个实例的每个实例(如果存在)都会对它所参与的每个垃圾收集周期施加很小但非零的开销.在放弃对象之前在对象上调用SuppressFinalize可以防止将其移动到易碎队列中,但是不会消除由于对象一直存在于可终结队列中而导致的开销.
我建议不要将面向公众的对象实现为Finalize. Finalize方法有一些合法用途,但是覆盖它的类应避免保留对终结不需要的任何内容的引用(令人讨厌的是,如果finalizable对象持有对弱引用的唯一引用,则弱引用可能在终结器之前无效运行,即使弱引用的目标仍然有效).
内容总结
以上是互联网集市为您收集整理的c#-具有终结器的开销-在处理中有/没有SuppressFinalize全部内容,希望文章能够帮你解决c#-具有终结器的开销-在处理中有/没有SuppressFinalize所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。