什么时候对象的引用超出范围?

时间:2014-03-17 14:06:04

标签: vb.net garbage-collection scope

我一直在问自己很长一段时间,当确切的对象和变量超出范围并被垃圾收集时。在这方面,参考和价值类型之间的区别也是如此。

例如,如果我使用

Private Sub Foo()
  Dim ob as Integer = 1
End Sub

我的理解是,当Sub运行并且相关内存再次被释放时,变量超出范围。我认为这与引用相同。但是,我可以做以下

Private Sub Foo()
  Dim frm1 as New Form1
  frm1.Show()               'Edit made here!
End Sub

并打开相关表格,即使子表格立即结束也是如此。因此,似乎存在以某种方式保持打开的引用,因此不会丢弃新的表单实例。也许表格有一些特别之处。 但是其他一些随机物呢?

Private Sub Foo()
  Dim ob as New MyRandomClass
End Sub

此对象是否会像表单一样持久存在?

有人可以了解范围的细节以及变量,对象和表格之间的差异(在我看来,与C#相比,在VB.net中并不是非常简单)。

1 个答案:

答案 0 :(得分:3)

在.NET中,了解value types and reference types之间的区别非常重要。值类型主要是在堆栈上分配的基本类型。退出方法后,将释放此内存。第一个示例就是这种情况(Integer是值类型)。

相比之下,类是引用类型。这适用于表单和MyRandomClass。对于引用类型,内存在托管堆上分配。仅在堆栈上分配对指向堆上位置的内存的引用。如果对堆上对象的所有引用都超出范围,则堆上的内存也会在稍后的时间由Garbage Collector释放。

这是您的第3个示例中发生的事情:您在堆上分配一个对象,其中有一个名为ob的引用指向它。在方法结束时,将释放引用ob,但堆上的对象仍将存在,直到垃圾收集器释放它为止。

然而,你的第二个样本确实是一个特例。您创建了Form1的新实例,并将引用存储在frm1中。调用Show时,表单将成为应用程序用户界面的一部分。由于它是非模态形式,它会显示在屏幕上,但是应用程序的执行不会等到表单关闭。应用程序的用户界面线程用于处理表单的消息,直到它关闭为止。因此,虽然最初用于创建表单的表单已经超出范围,但还有其他一些对表单的引用。表单关闭后,内存将被释放,因为它不再有活动引用。