【发布时间】:2018-02-11 22:47:05
【问题描述】:
更新:
对不起,我很困惑。混淆可能来自对 GC/Dispose 的旧观念与新观念。
如果你看这里(虽然不再维护)官方Microsoft Documentations,它表明Dispose模式也用于释放托管资源:
protected override void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Release **managed** resources. (!!!!!)
}
// Release unmanaged resources.
// Set large fields to null.
// Call Dispose on your base class.
disposed = true;
}
base.Dispose(disposing);
}
这与new version中所写的内容相反,其中指出:
托管内存(使用 C# 运算符 new 分配的内存)不 需要明确释放。它会自动释放 垃圾收集器 (GC)。
也许这只是文档中的一个错误,让我失望了(该死的微软)。但也许——可能是在 GC 的早期,它并没有那么受信任,并且指导方针是“如果你知道自己在做什么,你可以清理自己”。现在它是如此值得信赖,以至于指导方针是“关于永远不要使用的托管资源,我们比你更了解”。如果没记错的话—— 那么这里显然有一些变化或转变。
至于问题 - 我不会做任何事情,让 GC 做它最了解的事情。
老问题:
我有一个 TreeView ViewModel 类,其中包含节点,它们是递归类(它们可以包含自己)。
例如
class RootViewModel // root
{
List<ItemViewModel> Children = new List<ItemViewModel>();
}
class ItemViewModel // node
{
List<ItemViewModel> Children = new List<ItemViewModel>();
}
在某些时候,来自 TreeView 的所有数据都被传输/保存到其他对象,我不再需要 TreeView。我猜我需要处理掉它? (当包含 ViewModel 的窗口关闭时,ViewModel 类对象保存在静态变量中)。
我需要自己处理每个节点(递归处理)还是将根对象设置为 null 并调用 GC 就足够了?
我应该注意,我的处置没有任何非托管资源,我只是将子列表中的所有子节点都设置为 null。
再说一遍 -
- 选项A:将静态对象设置为null,调用GC.Collect()。
-
选项B:递归设置所有节点为null,设置静态对象为null, 调用 GC.Collect()。- 到目前为止,根据答案和 cmets 似乎是不可能的 - 选项 C:GC 发现您停止使用静态对象,因此它会自行处理它。
【问题讨论】:
-
如果您的解决方案包括强制垃圾回收的要求,那么您做的事情非常非常错误。此外,您似乎对一次性用品和垃圾收集之间的关系有一些错误的看法;请记住,处置是释放不是垃圾收集的资源。您的任何选择都不是正确的做法。
-
您真正想要解决的问题是什么?
-
那么您需要进行一些以用户为中心的测量。您的用户有什么问题?一旦您可以衡量该问题,您就可以进行实验并发现您的更改是在经验上改善还是降低了用户体验。我注意到导致垃圾收集通常会降低用户体验,因为它们会使应用程序无响应。如果您没有影响用户的问题,那么请将您的宝贵时间花在“解决”没有人解决的问题之外的事情上。
-
将模型存储在静态变量中似乎是一个坏主意,它会导致您试图解决的问题。你能避免将它存储在静态变量中吗?例如。将其存储在您的 ViewForm 中,因此当表单关闭时,模型将被 GC 收集。
-
另请参阅我的回答下 Brian 的评论。