【问题标题】:Clearing a Collection of Collections - clear every item first, or just clear all at once?清除收藏集 - 先清除所有物品,还是一次性清除所有物品?
【发布时间】:2010-10-29 15:20:34
【问题描述】:

假设我有一个本身包含集合的集合;例如,字典(字符串,列表(MyClass))。如果我想完全清除集合,在清除父集合之前清除每个单独的子集合是否有意义,如下所示:

For Each ListDef As KeyValuePair(Of String, List(Of MyClass)) In MasterDictionary
    Dim ThisList As List(Of MyClass) = ListDef.Value
    ThisList.Clear()
Next

MasterDictionary.Clear()

或者这真的只是简单地完成了:

MasterDictionary.Clear()

我想问是否有任何理由——性能、安全性、清晰度等——使用第一种方法。我通常自己使用第二种方法,因为我假设它隐含地实现了第一种方法的作用。但是我们都知道有时假设是多么危险。所以这个问题。

编辑:今天,在我自己的应用程序中,我看到了令人信服的证据,表明在某些情况下第一种方法可能更可取。在我的应用程序中,当用户单击标有“加载数据”的按钮时,会填充一些全局集合(包含列表的字典,如上面的示例代码)。当用户点击“卸载数据”重新开始时,以前我是使用上面的第二种方法清除这些集合。

问题是当用户第二次点击“加载数据”时,应用程序会突然变得很慢。最终它会再次完成对集合的填充,但速度很慢。在我终于尝试了上面的第一种方法之前,我无法弄清楚如何解决这个问题。现在重新加载和重新填充集合的速度与第一次加载一样快。

根据迄今为止发布的答案,听起来我必须有“其他代码”引用子集合;但是,在我看来,它不像我那样。我引用这些孩子的唯一地方是我迭代他们的父母的地方;如果父母被清除,那么他们应该没有代码知道的孩子,对吗?

希望有人可以帮助我了解这些参考资料是如何仍然存在的,或者我忽略了什么。

【问题讨论】:

  • 根据您在问题中显示的代码示例,没有理由认为第一个片段的执行与第二个片段有任何不同;在任何一种情况下,最终都会清除顶级字典,并且(据称)没有任何内容引用最初在其中的任何元素。解释第二次加载的性能差异的唯一方法是是否发生了其他事情,但要确定有必要获取有关加载和卸载实际执行的更多信息。

标签: .net list collections dictionary


【解决方案1】:

这取决于您的代码是如何使用的。

如果您在某处有其他代码引用任何 List(Of MyClass),那么显然,这些列表对于使用第一种方法的其他代码将是空的,而在第一种方法中则不是这样。

如果有任何性能差异,我不知道,我想找出答案的最好方法是尝试分析它。人们可能会认为第一种方法最初使用更多的 CPU 能力,但在 GC 轮期间可能更少 - 但实际上这是一个分析有意义的情况:)。

【讨论】:

    【解决方案2】:

    如果没有其他对“子”集合的引用,则“父”集合上的 Clear() 将导致子集合(以及其中的项目)最终被清理。我想说,只要没有子集合的元素实现 IDisposable,你就是安全的,因为这意味着它们有一些资源被锁定,并且不正确地处理它们可能会导致问题。

    【讨论】:

      【解决方案3】:

      在这两种情况下,您都不会处理子集合中包含的单个元素的任何处置问题。在这种情况下,两者应该是相同的。

      存在差异的一个地方是其他代码是否直接引用了任何单个子集合。如果您在另一部分代码中持有对 List(Of MyClass) 之一的引用,则第一种方法将清除列表中的元素(并影响您的其他代码)。第二种方法不会这样做,因为它会单独留下 List。

      如果没有其他引用被持有,那么第二种方法只是等待 GC 清理元素。在这两种情况下,单个引用都将由 GC 处理,因此性能差异可以忽略不计。就个人而言,我会使用第二种方法,因为我相信它更清晰(并且更容易编写),并且在大多数情况下效果不会那么令人惊讶,特别是如果您在其他地方使用该列表。

      【讨论】:

      • 自从我看过我提出这个问题的代码以来,已经有 很长 时间了。回想起来,我很确定我一定一直在做你在这里猜到的事情——在其他地方持有对子集合的引用——而没有意识到这一点。老实说,最初的项目真是一团糟。我刚刚开始,还有很多东西要学。我现在为后代接受这个答案,因为我认为它代表了向可能处于这种情况下的另一位开发人员提供的最明智的建议(我自己什至没有此代码可以查看)。
      猜你喜欢
      • 1970-01-01
      • 2016-03-14
      • 2020-11-15
      • 1970-01-01
      • 2019-05-06
      • 1970-01-01
      • 2017-02-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多