【问题标题】:Does calling Clear disposes the items also?调用 Clear 是否也会处理这些项目?
【发布时间】:2010-12-30 10:53:50
【问题描述】:

很多时候有一个明确的方法,从集合中删除所有项目,这些项目是否也被丢弃。

喜欢,

toolStripMenuItem.DropDownItems.Clear();

足够了,或者我应该这样打电话:

foreach (ToolStripItem item in toolStripMenuItem.DropDownItems)
{
  toolStripMenuItem.DropDownItems.Remove(item);
  item.Dispose();
}

编辑:嗯 ToolStripItem 是一个例子而不是一个问题,对于那些说 Clear 就足够了我找到了另一个例子,TabControl 也有项目集合和 clear 方法。但是 TabControls 可以有复杂的控件(至少我有),这些控件需要显式 Dispose(即使它们在某个时候被 GC 自动 Dispose,因为它们占用了大量内存)。我想最好的答案是 divo 评论来处理项目,然后调用 clear。

【问题讨论】:

  • 我相信作者是一个 C/C++ 开发人员,他“需要”在每个函数中处理资源,即使在 .NET 中不是这种必要性。我怀疑从集合中清除项目后完成/处置项目的必要性。
  • @serhio - 在 .NET 中,在 IDisposable 资源上调用 Dispose() 仍然是你的工作,或者确保 Dispose() 被其他代码调用。
  • 使用 .NET Reflector 是查看 ToolStripItemCollection.Clear() 是否在集合项上实际调用 Dispose 的好方法。如果您查看反汇编的源代码,您会发现它没有。
  • @Marc:告诉我一个原因,我为什么要处理 ToolStripItem?我只是把这个任务留给了 GC。
  • @serhio:ToolStripItem 是否实际使用非托管资源是一个实现细节。事实上,它实现了IDisposable,并且IDisposablecontract 说“这个对象可能直接或间接使用一些非托管资源,你应该在用完它时将其丢弃。 "

标签: c# .net collections dispose


【解决方案1】:

问:会吗?

答: - Clear 不会处理这些项目(它们可以用于您应用程序的其他部分)。

那么,如果您的 ToolStripItems 是标准的 .NET 项目,Clear 是否就足够了?经过一番思考,我会说“可能不会”。

是的,如果您在应用程序的其他部分对 ToolStripItem 有任何引用,那么 .NET GarbageCollector 将销毁(使用类 destructor ) 它自动。但是,它不会调用 Dispose(true) 方法,但这是表单的 IDisposable 组件所必需的。

阅读提案thisthis

实际上,我相信您需要明确地Dispose 您的项目,就像 ToolStrip 的 Dispose 方法所做的那样(将 this 替换为 yourToolStrip ):

if (!this.Items.IsReadOnly)
{
    for (int i = this.Items.Count - 1; i >= 0; i--)
    {
        this.Items[i].Dispose();
    }
    this.Items.Clear();
}

编辑

我还创建了the following thread 来更一般地澄清这个问题。

【讨论】:

  • 不,如果集合中的对象需要处理,clear 是不够的。终结器可能处置对象;但是,它何时会发生并不确定它是否会发生(请参阅msdn.microsoft.com/en-us/library/system.object.finalize.aspx:“Finalize 方法可能无法完成或在以下特殊情况下可能根本不会运行...... "
  • 我怀疑在从集合中清除项目后完成/处置项目的必要性。
  • 嗨,serhio,这不应该是“如果你有任何参考资料”应该是“如果你没有任何参考资料”
  • 我想它仍然令人困惑,如果您在应用程序的其他部分有任何引用,为什么 GarbageCollector 会自动销毁(Dispose)它?因为你仍然有参考。对不起,这句话让我很困惑。
  • @divo:.NET 对象确实有一个析构函数 ~() msdn.microsoft.com/en-us/library/66x5fx1b%28VS.80%29.aspx 隐式使用 Finalize。重写析构函数时,您甚至可以删除 Finalize 方法(即使这没有意义)
【解决方案2】:

当您处理非托管内存、共享资源或大内存区域时,您应该依赖Dispose() 调用。好像不是这种情况。

【讨论】:

    【解决方案3】:

    调用Clear 不会释放项目,但会删除集合中对项目的引用。如果这是对项目的唯一引用,它们将在某个时候自动被垃圾收集(您无法预测,但您可以使用 GC 类进行控制)。

    【讨论】:

    • 依靠垃圾收集器进行处理是不安全的。请参阅我对 serhio 答案的评论。
    • @divo:如果您的 ToolStripItem 是标准 WinForm 对象,则有必要用垃圾填充代码。
    • @serhio:在“普通”Windows 窗体应用程序中,通常不需要显式调用 Component.Dispose(),因为它已经被调用,然后窗体关闭(请参阅后面的设计器生成的代码,它覆盖Dispose 并在表单中使用的每个组件上调用Dispose)。但是,如果您在运行时动态添加和删除组件,则您有责任明确处置这些组件。
    • @serhio: Control Component: public class Control : Component, IDropTarget, ISynchronizeInvoke, IWin32Window, IBindableComponent, IComponent, IDisposable
    • @serhio:我建议您使用 Reflector 深入研究 .NET 源代码。您将看到Form 派生自Control,它在其自己的Dispose 方法中对其所有子组件调用Dispose
    【解决方案4】:

    我不这么认为,此外,它可能会导致许多逻辑问题,因为您可能在集合中引用了该对象以供以后使用。如果您没有对该对象的引用,垃圾收集器将在稍后处理该对象

    【讨论】:

      猜你喜欢
      • 2013-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多