ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c#-具有终结器的开销-在处理中有/没有SuppressFinalize

2019-11-20 16:08:16  阅读:242  来源: 互联网

标签:finalizer idisposable dispose c suppressfinalize


假设以下内容:

>班级仅管理成员.
>一些成员实现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对象持有对弱引用的唯一引用,则弱引用可能在终结器之前无效运行,即使弱引用的目标仍然有效).

标签:finalizer,idisposable,dispose,c,suppressfinalize
来源: https://codeday.me/bug/20191120/2045129.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有