VB.Net中集合中对象的生存期

VB.Net中集合中对象的生存期,vb.net,collections,garbage-collection,tabcontrol,lifetime,Vb.net,Collections,Garbage Collection,Tabcontrol,Lifetime,我试图在下面的代码中计算出tmptabpage的生存期。假设表单有一个名为MyTabControl的空TabControl,有一个名为NameCollection的字符串集合 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load For Each itm In NameCollection Dim tmpTabPage a

我试图在下面的代码中计算出tmptabpage的生存期。假设表单有一个名为MyTabControl的空TabControl,有一个名为NameCollection的字符串集合

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    For Each itm In NameCollection
        Dim tmpTabPage as New TabPage(itm.toString)

        'Add Controls to tmpTabPage

        MyTabControl.TabPages.Add(tmpTabPage)
    Next
End Sub

因为tmpTabPage的范围是For/Next块,所以它的生命周期通常会一直到块结束,对吗?但是,由于它被添加到一个范围在块之外的集合中,它的生存期是否与该集合相同,或者在本例中是MyTabControl?最后,如果我调用MyTabControl.TabPages.Clear,那么集合中的TMPTabPage会被销毁吗?还是它们只是坐在那里占用内存?

当无法获取时,.NET中的对象可以进行垃圾收集。在这种情况下,有一种方法可以通过
TabPages
集合访问
TabPages
,直到它从集合中删除或选项卡控件本身符合收集条件

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    For Each itm In NameCollection
        Dim tmpTabPage as New TabPage(itm.toString)

        'Add Controls to tmpTabPage

        MyTabControl.TabPages.Add(tmpTabPage)
    Next
End Sub
现在,当一个对象符合垃圾收集的条件时,这并不意味着它会立即被垃圾收集——垃圾收集会根据一些相当复杂的启发式方法在不同的时间运行,而且还会有“几代”内存,这使得事情更难预测

但基本上:

  • 您不必担心添加到集合中的对象会被神秘地收集并导致问题
  • 您通常不需要担心对象会永远泄漏内存。当然,在某些情况下,当您不再使用某个对象时,您确实需要采取一些主动步骤来确保该对象符合收集条件,但这种情况相对较少。(根据我的经验,它们通常与静态变量和/或事件相关。)

因为soemthing引用了将不会处理的控件

是的,如果您没有在目录中添加对它们的引用,则生命周期将一直持续到程序结束


清除操作将从集合中删除对象,并且如果没有其他对它们的引用(您描述的情况下不会出现这种情况),这些对象将被垃圾回收。

您只将TabPage对象的引用添加到集合中,而不是对象TmpTabPage。在本例中,tmpTabPage对象仅用于分配内存。

从控件(包括TabPage)派生的类的主要功能是Dispose()方法。Winforms不受自动垃圾收集的影响,它保留一个内部表,将控件的句柄映射到控件引用。这就是为什么,比如说,主窗体不会突然被垃圾收集,即使程序没有保留对它的引用

将TabPage添加到TabControl的集合将负责自动处理。这同样适用于TabControl,它将被添加到表单的Controls集合中。正常的事件链是程序或用户关闭表单。Form类迭代其子控件并调用其Dispose()方法。TabControl在其Dispose()方法中执行相同的操作,即处理选项卡页。Windows窗口在此过程中被销毁,从映射表中删除句柄,现在允许垃圾收集器最终为控件收集托管包装

有一个让许多Winforms程序员陷入麻烦的令人讨厌的陷阱。如果您从其父控件的集合中删除控件,则您有责任自行处理它。移除它不会自动处理它。Winforms通过将控件临时重新设置为名为“parking window”的隐藏窗口的父级,使本机窗口保持活动状态。很好的特性,它允许您将控件从一个父控件移动到另一个父控件,而无需销毁和重新创建控件

但这里的关键词是“暂时”。仅当您下一次重新租入控件时,这是暂时的。因此,它会从停车窗口移动到新的父对象。如果你不真的重新租它,那么它将永远活在停车窗上。吞噬资源直到程序终止。这就是所谓的泄漏。如果Windows拒绝创建另一个窗口,而您已经创建了10000个窗口,则会导致程序崩溃

ControlCollection.Clear()方法在这里尤其有害。它不处理控件,它们都被移动到停车窗口。如果不打算这样做,那么您必须自己对它们调用Dispose()