是否需要在VBA函数中将对象设置为Nothing

时间:2009-02-05 17:47:45

标签: vba ms-access access-vba office-2003

我总是读到,一旦我完成了对象,建议将对象设置为空。但我通常只在表格内的函数中使用它们。

在保留函数范围时是否丢失了引用并释放了内存,而不管将对象设置为Nothing?

即。是否真的有必要这样做:

Set db = Nothing
Set record_set = Nothing

7 个答案:

答案 0 :(得分:71)

VB使用所谓的“引用计数”垃圾收集器。

基本上,当变量超出范围时,引用对象上的引用计数器会递减。将对象引用分配给另一个变量时,引用计数器会递增。

当计数器达到零时,该对象已准备好进行垃圾回收。一旦发生这种情况,对象资源就会被释放。函数局部变量很可能引用一个引用计数永远不会大于1的对象,因此当函数结束时将释放对象资源。

将变量设置为Nothing是明确减少参考计数器的方法。

例如,您读入文件,并在Nothing调用后立即将文件对象变量设置为ReadAll()。文件句柄将立即释放,您可以花时间处理其内容。

如果未设置为Nothing,则文件句柄可能会打开超过绝对必要的时间。

如果您不是“必须解锁宝贵资源”的情况,只需让变量超出范围即可。

答案 1 :(得分:14)

垃圾收集很少是完美的。即使在.NET中,也有时强烈建议您尽快提示系统进行垃圾收集。

出于这个原因,我完成了关闭并设置为 Nothing 记录集。

答案 2 :(得分:12)

Microsoft DAO帮助和Access Developer Reference中“Recordset.Close”帮助主题的最后一行是:

  

“Close方法的替代方法是   设置对象变量的值   没什么(设置dbsTemp = Nothing)。“

http://msdn.microsoft.com/en-us/library/bb243098.aspx

考虑到这一点,来自Microsoft知识库的this article标题为“如何在使用数据访问对象(DAO)后防止数据库膨胀”,告诉您如果不需要,则应明确关闭数据库膨胀。你会注意到这篇文章对细节有点模糊; “原因”部分尚不清楚,几乎到了胡言乱语的程度。

http://support.microsoft.com/kb/289562

  

症状:Microsoft Access数据库   已经开始膨胀(或迅速增长)   在实现数据访问之后   对象(DAO)打开记录集。

     

原因:如果你没有发布   每次你记录集的记忆   循环遍历记录集代码,DAO   可以重新编译,使用更多的内存和   增加数据库的大小。

     

更多信息:创建时   Recordset(或QueryDef)对象   代码,显式关闭对象时   你完蛋了。 Microsoft Access   自动关闭Recordset和   QueryDef对象最多   情况。但是,如果你   明确关闭你的对象   代码,你可以避免偶尔   对象保留的实例   开。

最后,让我补充一点,我已经使用Access数据库15年了,而且我几乎总是让我的本地声明的记录集变量超出范围而不显式使用Close方法。我没有对它进行任何测试,但似乎并不重要。

答案 3 :(得分:2)

当变量超出范围时,应该清理引用。据推测,随着软件的更新版本的改进,这种情况有所改善,但有一段时间不可靠。我认为将变量明确设置为“Nothing”仍然是一种很好的做法。

答案 4 :(得分:2)

当您使用ASP classic(服务器端脚本)时,在使用它们时将所有对象设置为空是导入的,因为它们在[虚拟]服务器关闭之前不会超出范围。

出于这个原因,所有MS VB脚本示例始终显示对象被关闭并设置为空。因此,脚本摘录可以在ASP经典的环境中使用,其中对象不会超出范围。

在很少有其他情况下,您希望编写长时间运行的进程,其中对象不会超出范围,如果您没有显式释放对象,则会发现自己的物理内存不足。

如果您发现自己编写ASP经典编码,或者出于其他原因在全局范围内运行进程,那么是的,您应该明确地释放对象。

答案 5 :(得分:1)

我通常总是把它放在我的程序的末尾,或者如果我使用的是模块级的那个,则用它调用“CloseRecordSet”子:

Private Sub Rawr()
On Error GoTo ErrorHandler

    'Procedural Code Here.

    ExitPoint:
        'Closes and Destroys RecordSet Objects.
        If Not Recset Is Nothing Then
            If Recset.State = 1 Then
                Recset.Close
                Conn.Close
            End If
            Set Recset = Nothing
            Set Conn = Nothing
        End If
        Exit Sub

    ErrorHandler:
        'Error Handling / Reporting Here.
        Resume ExitPoint
End Sub

然而,程序结束,(无论是正常还是由于错误),对象被清理并且资源是免费的。

这样做是非常安全的,因为它你可以把它打开并且它只会做关闭或破坏记录集/连接对象的必要条件,因为它已经被关闭(由于运行时错误或只是提早关闭它,这只是确保)。

它真的没那么麻烦,当你完成它们时,它总是最好清理你的对象,以便不管程序中发生什么,都可以立即释放资源。

答案 6 :(得分:-1)

试试这个

If Not IsEmpty(vMyVariant) Then
    Erase vMyVariant
    vMyVariant = Empty
End If