为什么没有引用计数+垃圾收集在C#中?

我来自C ++背景,并且我一直在使用C#大约一年。 像许多其他人一样,我为什么决定性的资源管理不是内置于语言中而感到沮丧。 我们有了处置模式,而不是确定性的析构函数。 人们开始怀疑是否通过他们的代码传播IDisposable癌症是值得的。

在我的C ++偏见的大脑中,似乎使用引用计数的智能指针与确定性析构函数是垃圾回收器的一个重要步骤,它需要您实现IDisposable并调用dispose来清理非内存资源。 诚然,我不是很聪明......所以我纯粹是从一种渴望中去问这个问题,以便更好地理解为什么事情是这样的。

如果C#被修改,那么:

对象被引用计数。 当对象的引用计数变为零时,将在对象上确定性地调用资源清理方法,然后将该对象标记为垃圾回收。 垃圾收集发生在未来的某个非确定性时间,在这个时间点回收内存。 在这种情况下,您不必实现IDisposable或记得调用Dispose。 如果您要释放非内存资源,则只需实施资源清理功能即可。

  • 为什么这是一个坏主意?
  • 这会否击败垃圾收集器的目的?
  • 实施这样的事情是否可行?
  • 编辑:从目前为止的评论,这是一个坏主意,因为

  • 没有参考计数,GC更快
  • 处理对象图中的周期问题
  • 我认为第一是有效的,但第二个很容易处理使用弱引用。

    速度优化大于你的缺点:

  • 可能无法及时释放非内存资源
  • 可能会很快释放非内存资源
  • 如果您的资源清理机制是确定性的并且内置于该语言中,则可以消除这些可能性。


    Brad Abrams在发布.Net框架期间发布了一封Brian Harry的电子邮件。 它详细介绍了很多未使用引用计数的原因,即使早期的优先事项之一是与使用引用计数的VB6保持语义等价。 它研究了一些可能性,比如让某些类型的ref被计数,而不是其他类型( IRefCounted !),或者计算具体实例,以及为什么这些解决方案都不被认为是可接受的。

    因为[资源管理和确定性定稿问题]是一个非常敏感的话题,所以我尽可能在我的解释中尽可能精确和完整。 我为邮件的长度道歉。 这封邮件的前90%试图说服你,这个问题真的很难。 在最后一部分中,我将谈论我们正在尝试做的事情,但您需要第一部分来了解我们为什么要看这些选项。

    ...

    我们最初开始时假设解决方案将采用自动参考计数的形式 (所以程序员不能忘记)以及一些其他的东西来自动检测和处理周期。 ......我们最终得出结论,这在一般情况下不起作用。

    ...

    综上所述:

  • 我们认为解决循环问题非常重要,不要强迫程序员理解,追踪和设计这些复杂的数据结构问题。
  • 我们要确保我们具有高性能(速度和工作集)系统,我们的分析表明, 对系统中的每个单个对象使用参考计数不会使我们实现这一目标
  • 由于各种原因,包括构图和投射问题, 没有简单的透明解决方案,只需要将需要它的对象计算在内
  • 我们选择不选择为单一语言/上下文提供确定性定稿的解决方案, 因为它禁止与其他语言互操作 ,并通过创建语言特定版本来引起类库的分叉。

  • 垃圾收集器不要求您为每个定义的类/类型编写一个Dispose方法。 你只需要定义一个,当你需要明确地做一些清理工作; 当你明确分配本地资源时。 大多数情况下,GC只是回收内存,即使你只是做一些像new()这样的对象。

    GC确实引用了计数 - 但是它通过每次执行集合时发现哪些对象“可达”( Ref Count > 0 )以不同方式进行Ref Count > 0 ......它只是不以整数计数器方式执行。 。 无法到达的对象被收集( Ref Count = 0 )。 通过这种方式,运行时不必在每次分配或释放对象时都执行管家/更新表......应该更快。

    C ++(确定性)和C#(非确定性)之间唯一的主要区别是对象将被清理。 您无法预测在C#中收集对象的确切时间。

    Umpteenth plug:我建议通过C#阅读Jeffrey Richter关于CLR中GC的独立章节,以防您真正对GC的工作方式感兴趣。


    在C#中尝试引用计数。 我相信,发布Rotor(CLR的参考实现,其源代码可用)的人确实引用了基于计数的GC,以便了解它如何与世代相比。 结果令人惊讶 - “股票”GC太快了,它甚至不好笑。 我不记得我听到的是什么,我认为它是Hanselmuntes播客之一。 如果你想看到C ++基本上与C#的性能比较 - 谷歌Raymond Chen的中文字典应用程序。 他做了一个C ++版本,然后Rico Mariani做了一个C#版本。 我认为需要Raymond 6次迭代才能最终击败C#版本,但那时他不得不放弃C ++的所有优秀的面向对象,进入win32 API级别。 整个事情变成了性能黑客。 同时,C#程序仅进行了一次优化,最终仍然看起来像一个体面的面向对象项目

    链接地址: http://www.djcxy.com/p/54527.html

    上一篇: Why no Reference Counting + Garbage Collection in C#?

    下一篇: Setting Objects to Null/Nothing after use in .NET