Effective C#第二章:.Net资源管理2010-12-09 博客园 Wu.Country@侠缘译一个简单的事实:.Net应用程序是在一个托管的环境里运行的,这个环境和 不同的设计器有很大的冲突,这就才有了Effective C#。极大限度上的讨论这个 环境的好处,须要把你对本地化环境的想法改变为.Net CLR。也就意味着要明白 .Net的垃圾回收器。在你明白这一章里所推荐的内容时,有必要对.Net的内存管 理环境有个大概的了解。那我们就开始大概的了解一下吧。垃圾回收器 (GC)为你控制托管内存。不像本地运行环境,你不用负责对内存泄漏,不定指针 ,未初始化指针,或者一个其它内存管理的服务问题。但垃圾回收器前不是一个 神话:你一样要自己清理。你要对非托管资源负责,例如文件句柄,数据链接, GDI+对象,COM对象,以及其它一些系统对象。这有一个好消息:因为GC 管理内存,明确的设计风格可以更容易的实现。循环引用,不管是简单关系还是 复杂的网页对象,都非常容易。GC的标记以及严谨的高效算法可以检测到这些关 系,并且完全的删除不可达的网页对象。GC是通过对从应用程序的根对象开始, 通过树形结构的“漫游”来断定一个对象是否可达的,而不是强迫每 个对象都保持一些引用跟踪,COM就是这样的。DataSet就是一个很好的例子,展 示了这样的算法是如何简化并决定对象的所属关系的。DataSet是一个DataTable 的集合,而每一个DataTable又是DataRow的集合,每一个DataRow又是DataItem 的集合,DataColum定义了这些类型的关系。这里就有一些从DataItem到它的列 的引用。而同时,DataTime也同样有一个引用到它的容器上,也就是DataRow。 DataRow包含引用到DataTable,最后每个对象都包含一个引用到DataSet。(译注:作者这里是想说:你看,这么复杂的引用关系,GC都可以轻松的 搞定,你看GC是不是很强大?)如果这还不够复杂,那可以创建一个 DataView,它提供对经过过滤后的数据表的顺序访问。这些都是由 DataViewManager管理的。所有这些贯穿网页的引用构成了DataSet。释放内存是 GC的责任。因为.Net框架的设计者让你不必释放这些对象,这些复杂的网页对象 引用不会造成问题。没有必须关心这些网页对象的合适的释放顺序,这是GC的工 作。GC的设计结构可以简化这些问题,它可以识别这些网页对象就是垃圾。在应 用程序结束了对DataSet的引用后,没有人可以引用到它的子对象了(译注:就是 DataSet里的对象再也引用不到了)。因此,网页里还有没有对象循环引用 DataSet,DataTables已经一点也不重要了,因为这些对象在应用程序都已经不 能被访问到了,它们是垃圾了。垃圾回收器在它独立的线程上运行,用 来从你的程序里移除不使用的内存。而且在每次运行时,它还会压缩托管堆。压 缩堆就是把托管堆中活动的对象移到一起,这样就可以空出连续的内存。图2.1 展示了两个没有进行垃圾回收时的内存快照。所有的空闲内存会在垃圾回收进行 后连续起来。

图2.1 垃圾回收器不仅仅是移动不使用的内存,还移除动其它的对象 ,从而压缩使用的内存,让出最多的空闲内存。