在《编写对象的新实例》一文中,我介绍了创建对象的新实例的各种方法。相反的问题是处理对象,在VB.NET中您不必经常担心。NET包含一种称为垃圾收集器(GC)的技术,该技术通常安静而高效地处理幕后的一切。但有时,通常在使用文件流、sql对象或图形(GDI+)对象(即非托管资源)时,您可能需要控制在自己的代码中处理对象。
就像构造器(New关键字)创建新对象一样,析构函数是在对象被销毁时调用的方法。但有一个陷阱。创建.NET的人意识到,如果两段不同的代码实际上可以破坏一个对象,那么这就是bug的公式。因此.NETGC实际上处于控制之中,它通常是唯一可以销毁对象实例的代码。GC在决定销毁对象时销毁该对象,而不是在之前。通常,对象离开作用域后,由公共语言运行库(CLR)释放。当CLR需要更多空闲内存时,GC会销毁对象。所以底线是,您无法预测GC何时会实际销毁该对象。
(嗯……几乎所有时候都是这样。你可以调用GC.Collect并强制执行垃圾收集循环,但当局普遍认为这是一个坏主意,完全没有必要。)
例如,如果您的代码创建了一个Customer对象,那么该代码可能会再次破坏它。
但事实并非如此。(将对象设置为Nothing通常称为解除对对象的引用。)实际上,这只是意味着变量不再与对象关联。稍后,GC会注意到该对象可用于销毁。
顺便说一下,对于托管对象,这些都不是真正必要的。虽然像按钮这样的对象将提供一个Dispose方法,但不需要使用它,而且很少有人使用它。例如,Windows窗体组件被添加到名为components的容器对象中。关闭表单时,将自动调用其Dispose方法。通常,在使用非托管对象时,您只需担心这些问题,甚至只是为了优化您的程序。
释放对象可能持有的任何资源的推荐方法是调用对象的Dispose方法(如果有),然后取消对该对象的引用。
Customer.Dispose() Customer = Nothing因为GC将销毁孤立对象,无论您是否将对象变量设置为Nothing,都没有必要这样做。
另一种确保不再需要对象时销毁对象的推荐方法是将使用对象的代码放入Using块。Using块保证在代码使用完一个或多个这样的资源后可以对它们进行处理。
在GDI+系列中,经常使用Using块来管理那些讨厌的图形对象。例如
Using myBrush As LinearGradientBrush _ = New LinearGradientBrush( _ Me.ClientRectangle, _ Color.Blue, Color.Red, _ LinearGradientMode.Horizontal) <... more code ...> End Using当执行块的末尾时,myBrush将自动处理。
GC管理内存的方法与VB6管理内存的方法相比有了很大的改变。当引用的内部计数器达到零时,COM对象(由VB6使用)被销毁。但是很容易出错,所以内部计数器关闭了。(因为发生这种情况时内存被占用,其他对象无法使用,所以这被称为“内存泄漏”。)相反,GC实际上会检查是否有任何东西正在引用一个对象,并在没有更多引用时销毁它。GC方法在Java等语言中有着良好的历史,并且是.NET中的重大改进之一。
在下一页中,我们将查看IDisposable界面。。。需要在自己的代码中处置非托管对象时使用的接口。
如果您为自己的使用非托管资源的对象编写代码,则应该为该对象使用IDisposable接口。Microsoft通过包含一个代码片段为您创建正确的模式来简化这一过程。
--------单击此处显示插图单击浏览器上的“上一步”按钮返回--------
添加的代码如下所示(VB.NET 2008):
Class ResourceClass Implements IDisposable ' To detect redundant calls Private disposed As Boolean = False ' IDisposable Protected Overridable Sub Dispose( _ ByVal disposing As Boolean) If Not Me.disposed Then If disposing Then ' Free other state (managed objects). End If ' Free your own state (unmanaged objects). ' Set large fields to null. End If Me.disposed = True End Sub #Region " IDisposable Support " ' This code added by Visual Basic to ' correctly implement the disposable pattern. Public Sub Dispose() Implements IDisposable.Dispose ' Do not change this code. ' Put cleanup code in ' Dispose(ByVal disposing As Boolean) above. Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overrides Sub Finalize() ' Do not change this code. ' Put cleanup code in ' Dispose(ByVal disposing As Boolean) above. Dispose(False) MyBase.Finalize() End Sub #End Region End ClassDispose几乎是.NET中“强制”的开发人员设计模式。只有一种正确的方法可以做到这一点。你可能认为这段代码有魔力。没有。
首先要注意的是,内部标志disposed只会使整个过程短路,因此您可以随时调用Dispose(disposing)。
代码。。。
GC.SuppressFinalize(Me)... 通过告诉GC对象已经被释放(就执行周期而言,这是一个“昂贵”的操作),使您的代码更加高效。Finalize是受保护的,因为GC在对象被销毁时自动调用它。你不应该打电话给我。布尔处理告诉代码是您的代码启动了对象的处理(True),还是GC启动了对象的处理(作为Finalize子项的一部分)。请注意,使用布尔处理的唯一代码是:
If disposing Then ' Free other state (managed objects). End If处置对象时,必须处置其所有资源。当CLR垃圾收集器处置对象时,仅必须处置非托管资源,因为垃圾收集器会自动处理托管资源。
此代码段背后的思想是,添加代码以处理指定位置中的托管和非托管对象。
当您从实现IDisposable的基类派生类时,您不必重写任何基类方法,除非您使用其他也需要释放的资源。如果发生这种情况,则派生类应重写基类的Dispose(disposing)方法以处置派生类的资源。但是记住调用基类的Dispose(disposing)方法。
Protected Overrides Sub Dispose(ByVal disposing As Boolean) If Not Me.disposed Then If disposing Then ' Add your code to free managed resources. End If ' Add your code to free unmanaged resources. End If MyBase.Dispose(disposing) End Sub这个主题可能有点让人不知所措。这里解释的目的是“揭开”实际发生的事情,因为你能找到的大部分信息都不能告诉你!
...final。在编程中,可能会有错误,为了正确地执行程序,处理这些错误是很重要的。finalize是由垃圾回收器调用的方法。因此,所有这些术语都有不同的含义。final是一个关键字,用于防止更改变量、避免方法重写和避免扩展类。...
...hell中学习格式化、过滤和比较 学习在PowerShell中使用远程处理 使用PowerShell获取计算机信息 整个星期请继续关注本系列的其余部分。 使用批处理cmdlet 在本系列的前面,当我们向您介绍管道时,我们向您展示了如何获取一个cmdl...
...会遇到的。我们将向您展示如何使用jq命令从Linux命令行处理它。 json和jq JSON代表JavaScript对象表示法。这是一种允许数据以自我描述的方式编码成纯文本文件的方案。JSON文件中没有注释,内容应该是不言自明的。每个数据值都...
...调用的对象的方法。相比之下,RPC不是面向对象的,也不处理对象。相反,它调用已经建立的特定子例程。 RPC是一个基于C语言的比较老的协议,因此继承了它的范例。使用RPC,您可以得到一个看起来很像本地调用的过程调用。R...
...相机看不到的对象的过程。这意味着它留给Papervision引擎处理的多边形更少。剪裁是一个过程,通过该过程,可以拾取或剔除延伸到摄影机上方的多边形。剪裁允许所有多边形消失。 在视频游戏中,剪接方法的使用要多于剔除技...
...们在不同浏览器下的行为不同。人们会发现,某个浏览器处理对象的外部空间和内部空间,而另一个浏览器拒绝处理边距或填充。有时,可能会发现浏览器拒绝处理对象的任何空格—可能是边距或填充。这就解释了为什么某些页...
...后,对象将从堆内存中移除。 实施处置和定案 从内存中处理对象的过程称为dispose模式,该模式可用于访问非托管资源的对象,因为垃圾收集器无法回收非托管资源。实现“IDisposable”接口以及附加的Dispose(布尔)方法,要求释...
...OOP是一种编程范式。在OOP中,每个对象都能够接收消息、处理数据并向其他对象发送消息。因此,每个对象都是独立的,并且具有不同的角色或职责。 C++是一种通用的程序设计语言。它也是从原来的C语言发展而来的。它是由Bj...
...如何使用的? Ruby用于典型的脚本语言应用程序,如文本处理和“胶水”或中间件程序。它适用于小型的、特别的脚本任务,在过去,这些任务可能是用Perl解决的。用Ruby编写小程序就像导入所需的模块和编写类似“事件序列”...