【发布时间】:2015-05-28 23:48:53
【问题描述】:
我来自 C++ 背景,想听听 C# (.NET) 专家对以下问题陈述的一些想法,我愿意接受解决方法,但要求被冻结。
问题陈述:
拥有一个系统,一旦拥有的对象被删除,就会自动清理依赖对象(与下面解释的 GC 提供的有点不同。)
依赖对象可能有其他引用而不是其拥有对象,但一旦拥有对象被删除,依赖对象就需要离开
能够用存根对象(占位符)引用替换其他未完成的引用,因为实际对象不再退出
系统需要与对象无关,并且应该能够检测引用或用从 System.Object (.net) 继承的任何对象的存根替换它们
术语定义:
从属对象:始终需要所有者的对象,但也可能被其他对象引用。然而,依赖对象的生命周期将由拥有对象完全拥有。如果拥有对象被删除,则依赖对象必须被删除。
存根对象 这些是表示已删除引用的对象。
功能背景
为了能够支持功能需求,我们需要一个系统,该系统将自动清理所有者被删除的依赖对象,然后它会用存根替换其他引用以指示它所持有的对象已被删除或卸载,
用一个简单的例子来解释一下
Time T1 - 假设我们创建了一个 Line 对象。由于创建一条线需要一个起点和终点,因此它创建了 2 个点(Pt1 和 Pt2)对象。点对象被标记为从属对象,而线对象是所有者。所以在任何时候,如果我们删除 Line,它应该去删除 Pt1 和 Pt2。
时间 T2:我们创建两个新点 Pt3 和 Pt4(它们现在是独立的对象)
时间 T3:我们创建一个正在引用的曲线对象(Pt2、Pt3 和 Pt4)。这里 Pt2 的生命周期由 Line 对象控制。
时间 T4:我们从图形中删除 Line 对象,现在作为一项要求,此操作必须删除 Pt1 和 Pt2,因为它们是由 Line 创建的,并且 Line 对象已被删除。
时间 T5:由于曲线也引用了 Pt2,因此现在它的几何计算不完整,将参考存根对象。 Curve 对象将被标记为已损坏,以便在将来的某个时间点我们可以对其进行编辑以引用新点。
拥有这个系统的关键问题是因为删除是由.NET系统控制的,我们无法控制它。任何想法如何在 C# 或 .NET 中实现这一点(在 C++ 中,我们可以完全控制内存管理,因此可以在删除指针之前从指针确定活动引用并在内存中删除或替换它们)。
我了解垃圾收集器有其自身的巨大优势,但这是我们需要在基于 .NET 的 C# 模型中支持的关键要求。
任何想法,建议都表示赞赏。
【问题讨论】:
-
为什么需要这种精细的控制?
-
拥有一个系统,一旦拥有的对象被删除,它就会自动清理依赖对象(与下面解释的 GC 提供的有点不同。) 你真的不能在 C# 中强制删除对象。您可以运行
GC.Collect()并希望,但这不是“正确”的做法。 C# 没有确定性的终结/对象集合。你可以拥有的是Dispose(),它可以用来释放对象使用的部分资源(不是对象的“基本内存”) -
我给出的示例非常简单......我们现在拥有基于 C++ 的体系结构,但未来我们也将支持基于 .NET 的语言。我们热衷于基于几何和关联的计算软件,我们总是需要一直处理各种情况。如果将它们保存在不同的文件中,则可能会删除或根本不加载依赖关联。
-
你还没有解释为什么你需要控制它。我推断您不相信垃圾收集器能够快速清除内存(并且您假设它不能满足您的需求,或者您只是对缺乏控制感到恼火。无论哪种方式,如果你想完全控制内存使用,你就不能使用像 .NET 这样的托管框架。最好将你的库保留在 C++ 中并使用C++/CLI 编写一个 .NET API。
-
替换引用所指对象的唯一方法是修改引用。因此,当您删除线并因此删除点时,您需要修改存储在曲线中的参考。如果您不能/不会这样做,则需要将此类对象包装在可能有内容或没有内容的包装器中。然后曲线将引用它一直引用的同一个包装器,但您告诉包装器忘记内部点。无论哪种方式,这都必须明确地完成,.NET 中没有任何东西可以为您“自动解决”。
标签: c# .net memory-management dependency-management