在同一个对象上多次调用 new

Posted

技术标签:

【中文标题】在同一个对象上多次调用 new【英文标题】:Calling new multiple times on same object 【发布时间】:2012-09-29 10:04:40 【问题描述】:

我以前从未在此论坛上发过帖子,但经常使用它进行研究,但这次我找不到答案……也许我只是措辞不正确。

我在一个我已经工作了一段时间的 Compact Framework 项目中经常使用 SqlCeCommand,并且遇到了许多内存不足的问题,因此我正在尝试更好地优化非托管代码部分。

看看这个:

Dim SQLCmd as SQLCeCommand

SQLCmd = New SQLCeCommand
SQLCmd.Connection = conndb
... Process db stuff

SQLCmd = New SQLCeCommand
SQLCmd.Connection = conndb
... Process db stuff

SQLCmd = New SQLCeCommand
SQLCmd.Connection = conndb
... Process db stuff

SQLCmd.Dispose()

这样可以吗,还是每次在同一个对象上调用 New 时都会丢失内存?我这样做而不是保留对象的相同实例的原因是我不必每次都显式设置 SQLCmd 属性。因为有些可能使用参数,有些可能不使用,所以我认为使用 new 将是确保一切清晰的更简单方法。

有什么想法或更好的方法来解决这个问题吗?

【问题讨论】:

【参考方案1】:

在您的代码中,每次调用 New 时,先前的引用都会丢失,然后是垃圾收集器的工作来释放现在未引用的对象。当垃圾收集器框架决定是时候取回内存时会发生这种情况,因此不会立即发生

为了做得更好,您可以使用Using statement

Dim SQLCmd as SQLCeCommand 

Using SQLCmd = New SQLCeCommand 
    SQLCmd.Connection = conndb 
    ... Process db stuff 
End Using

Using SQLCmd = New SQLCeCommand 
    SQLCmd.Connection = conndb 
    ... Process db stuff 
End Using

Using SQLCmd = New SQLCeCommand 
    SQLCmd.Connection = conndb 
    ... Process db stuff 
End Using

通过这种方式,您可以自动为之前的 SqlCmd 调用 Dispose,并向垃圾收集器发出强烈提示以收集未使用的内存。

来自 MSDN

Managed resources are disposed of by the .NET Framework garbage collector (GC) without any 
extra coding on your part. You do not need a Using block for managed resources. However, 
you can still use a Using block to force the disposal of a managed resource instead of 
waiting for the garbage collector.

【讨论】:

感谢您的输入,这就是我对参考丢失的看法。 GC 是否仍然适用于非托管代码? 非托管代码超出了垃圾收集器的范围,基本上你就像在 C/C++ 中一样靠自己。如果您真的打算使用unmanaged resource,请记住垃圾收集器知道所有托管资源,并且在某个时间点,GC 将释放所有相关的内存和资源。 GC 不知道非托管资源,例如文件、流和句柄,因此,如果您没有在代码中明确清理它们,那么您最终会导致内存泄漏和资源锁定。 好的,我认为这可以解决问题。但是,您不能在 using 块之外声明变量。它必须像using SQLCmd = New SqlCeCommand 一样完成,它必须是using SQLCmd as New SqlCeCommand 的紧凑框架,因为它不支持后期绑定。感谢您的建议。

以上是关于在同一个对象上多次调用 new的主要内容,如果未能解决你的问题,请参考以下文章

您不应在一个对象上多次调用 Dispose(CA2202)[重复]

在一个包中多次调用同一个 plsql 过程

线程重复执行问题与线程池

Java中构造方法跟普通方法的区别?

javascript调用一个函数(对象),new和直接调用的区别

代码分析警告 CA2000:在对象“new ContainerControlledLifetimeManager()”上调用 Dispose