调用 Clear 是不是也会处理这些项目?

Posted

技术标签:

【中文标题】调用 Clear 是不是也会处理这些项目?【英文标题】: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 说“这个对象可能直接或间接使用一些非托管资源,你应该在用完它时将其丢弃。 " 【参考方案1】:

问:会吗?

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

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

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

阅读提案this 和this。

实际上,我相信您需要明确地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】:

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

【讨论】:

以上是关于调用 Clear 是不是也会处理这些项目?的主要内容,如果未能解决你的问题,请参考以下文章

Java项目中的异常处理情况

jni多个so

JAVA项目中的常用的异常处理情况1

JAVA项目中的常用的异常处理

JAVA项目中常用的异常处理情况总结

我是不是应该经常调用 EntityManager.clear() 以避免内存泄漏?