为什么处理一个肯定会很快被处理掉的物体呢?
假设我有一个例如点击按钮的程序。
我创建了一个Graphics对象。
显然我应该处理它,例如
using(Graphics gr__=this.CreateGraphics()) { }
或者在try-catch-finally的finally
中调用.Dispose()
。
但考虑到程序将很快结束。
假设我在程序的本地创建它(不是全局的,不是在使用中)。 但是当地的程序。
然后肯定像任何其他变量一样,它会在程序完成后自动处理掉,不是吗?
那么为什么我手动/明确地处理它很重要?
为什么我不能像任何其他变量一样自动垃圾收集?
当然它可能比’int’大一点,但它可能仍然很小,并且不会长时间记忆,因为程序结束如此之快。 甚至可能是在完成使用或调用Dispose()
,程序结束,因此我认为如果变量是程序的本地变量,它将被处理掉。 那么为什么要使用Dispose()
/ using
的显式垃圾收集呢?
Microsoft .NET类库通过System.Drawing命名空间为GDI +提供托管接口。 GDI +是基于C ++的,并产生对非托管对象的引用。 因此,配置System.Drawing命名空间的一次性对象非常重要,因为垃圾收集器不会自动处理非管理对象。 这些对象可能包含完成工作的终结器; 但是,您无法控制何时执行这些终结器。 等待终结器也会使堆混乱。 因此,最好明确地或通过using
-statement调用Dispose()
。
然后肯定像任何其他变量一样,它会在程序完成后自动处理掉,不是吗?
不幸的是,对于所有System.Drawing类,情况可能并非总是如此(编辑:读取dotctor答案)
还有一些其他棘手的类,比如Bitmap,虽然它是“托管”的,但是尺寸很小。 因此,无论什么时候处理都迟到,都会导致内存不足!
在发生内存泄漏之前,将未使用的对象进行浸渍是一种更好的做法。
但细节更复杂。
您可以在System.Drawing中搜索更多有关非托管资源的信息,以便更多地了解这一点。
这里有两个不同的概念。
- 处置
- 垃圾收集
这两个概念之间有很多不同。
虽然Graphics
在GC收集时会被处理掉,但为什么要等待GC运行并增加应用程序的内存镜头?
这是Graphics
析构函数的代码。
~Graphics() { try { this.Dispose(false); } finally { // ISSUE: explicit finalizer call // ISSUE: explicit non-virtual call __nonvirtual (((object) this).Finalize()); } }
阅读更多
垃圾收集的基本原理
GC,Finalize()和Dispose之间的关系是什么?
堆栈和堆的内容和位置是什么?
通常,您无法知道何时将对象进行垃圾回收,从而进行处置。
在处理之前,某些对象将保留对将使用您的内存或禁止某些操作的资源的引用。 因此,只要它们不再使用就可以立即处理它们。
我正在处理一个错误,在使用后无法删除临时SQLite数据库文件,但有时只是! 经过三天令人沮丧的研究,我发现问题是一个SQLite命令对象,没有及时处理。
所以使用你的using
😉