接上一篇.net框架读书笔记---CLR内存管理\垃圾收集(二),主要学习了终止化对象(实现了Finalize方法的对象),了解了终止化对象的弊端,学习了通过实现IDisposable接口,通过Dispose方法来清理非托管资源,从而减轻垃圾收集器的压力,本节继续学习。

一、使用实现了Dispose模式的类型

  System.IO.FileStream其基类Stream实现了IDisposable接口:

class Program
{
static void Main( string [] args)
{
// 创建要写入临时文件的字节
byte [] b = new byte [] { 1 , 2 , 3 , 4 , 5 };
FileStream fs = new FileStream( " temp.dat " , FileMode.Create);

// 写入临时文件
fs.Write(b, 0 , b.Length);

fs.Close();
// fs.Write(b, 0, b.Length); // 该行会爆出异常,试图写入关闭的文件

File.Delete( " temp.dat " );
}

}

  上面的代码如果File.Delete之前不调用close是会报错的,delete之前必须保证文件已经关闭。注意调用CLose方法后FileStream对象仍然在托管堆中,最后垃圾收集器会运行,并将该FileStream对象判定为可收集的垃圾。这时垃圾收集器本来应该调用FileStream对象上的Finalize方法,但是因为Dispose方法调用了GC的SuppressFinalize方法,所以Finalize方法不再被调用,对象的内存直接被回收。

二、C#的using语句

  上面的例子应该使用try/catch块中如下:

class Program
{
static void Main( string [] args)
{
// 创建要写入临时文件的字节
byte [] b = new byte [] { 1 , 2 , 3 , 4 , 5 };
FileStream fs = new FileStream( " temp.dat " , FileMode.Create);

try
{
// 写入临时文件
fs.Write(b, 0 , b.Length);
}
catch
{
// do someting
}
finally
{
fs.Close();
}
// fs.Write(b, 0, b.Length); // 该行会爆出异常,试图写入关闭的文件

File.Delete( " temp.dat " );
}

}

  对于上述代码C#提供了更为简洁的语法,可以使用using语句

class Program
{
static void Main( string [] args)
{
// 创建要写入临时文件的字节
byte [] b = new byte [] { 1 , 2 , 3 , 4 , 5 };

using (FileStream fs = new FileStream( " temp.dat " , FileMode.Create))
{
// 写入临时文件
fs.Write(b, 0 , b.Length);
}
// fs.Write(b, 0, b.Length); // 该行会爆出异常,试图写入关闭的文件

File.Delete( " temp.dat " );
}

}

  首先在using语句内初始化一个对象,并将其引用保存在一个变量内。然后在using大括号内访问该变量。当编译这段代码,编译器会自动创建一个try和finalily块。在finally内编译器会调用其Dispose方法,显然,using语句只能用于那些实现了IDisposable接口的类型。

  上面代码的IL为

.method private hidebysig static void Main( string [] args) cil managed
{
.entrypoint
// 代码大小 76 (0x4c)
.maxstack 4
.locals init ([ 0 ] uint8[] b,
[ 1 ] class [mscorlib]System.IO.FileStream fs,
[ 2 ] bool CS$ 4 $ 0000 )
IL_0000: nop
IL_0001: ldc.i4. 5
IL_0002: newarr [mscorlib]System.Byte
IL_0007: dup
IL_0008: ldtoken field valuetype ' <PrivateImplementationDetails>{7FD0DAA5-56D7-474F-B21D-5AECDF07BAFB} ' / ' __StaticArrayInitTypeSize=5 ' ' <PrivateImplementationDetails>{7FD0DAA5-56D7-474F-B21D-5AECDF07BAFB} ' :: ' $$method0x6000001-1 '
IL_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray( class [mscorlib]System.Array,
valuetype [mscorlib]System.RuntimeFieldHandle)
IL_0012: stloc. 0
IL_0013: ldstr " temp.dat "
IL_0018: ldc.i4. 2
IL_0019: newobj instance void [mscorlib]System.IO.FileStream::.ctor( string ,
valuetype [mscorlib]System.IO.FileMode)
IL_001e: stloc. 1
. try
{
IL_001f: nop
IL_0020: ldloc. 1
IL_0021: ldloc. 0
IL_0022: ldc.i4. 0
IL_0023: ldloc. 0
IL_0024: ldlen
IL_0025: conv.i4
IL_0026: callvirt instance void [mscorlib]System.IO.Stream::Write(uint8[],
int32,
int32)
IL_002b: nop
IL_002c: nop
IL_002d: leave.s IL_003f
} // end .try
finally
{
IL_002f: ldloc. 1
IL_0030: ldnull
IL_0031: ceq
IL_0033: stloc. 2
IL_0034: ldloc. 2
IL_0035: brtrue.s IL_003e
IL_0037: ldloc. 1
IL_0038: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_003d: nop
IL_003e: endfinally
} // end handler
IL_003f: nop
IL_0040: ldstr " temp.dat "
IL_0045: call void [mscorlib]System.IO.File::Delete( string )
IL_004a: nop
IL_004b: ret
} // end of method Program::Main

很明显可以看到try/finally,刚才试了一下,using不能处理异常的,看上面的IL会发现,其没有catch,感觉很不爽。using也不能滥用,避免过早的调用了dispose。导致应用程序产生异常(ObjectDisposeException)

【转】.net框架读书笔记---CLR内存管理\垃圾收集(三)相关推荐

  1. 【转】.net框架读书笔记---CLR内存管理\垃圾收集(四)

    弱引用 当一个根指向一个对象时,该对象不可能被垃圾收集器收集,在这种情况下,通常说存在一个该对象的强引用(strong reference).垃圾收集器还支持弱引用(weak reference)的概 ...

  2. 【转】.net框架读书笔记---CLR内存管理\垃圾收集(一)

    一.垃圾收集平台基本原理解析 在C#中程序访问一个资源需要以下步骤: 调用中间语言(IL)中的newobj指令,为表示某个特定资源的类型实例分配一定的内存空间. 初始化上一步所得的内存,设置资源的初始 ...

  3. 【转】.net框架读书笔记---CLR内存管理\垃圾收集(六)

    对象代龄 代龄是旨在提高垃圾收集器性能的一种机制.有以下几点: 对象越新,其生存期越短: 对象越老,其生存期越长: 对托管堆的一部分执行垃圾收集要比对整个托管堆执行垃圾收集速度要快. 在托管堆初始化时 ...

  4. 【转】.net框架读书笔记---CLR内存管理\垃圾收集(五)

    对象复苏     当一个终止化对象被认为死亡时,垃圾收集器可以强制使该对象获得重生(进入终止化可达队列),因为这样才能调用对象的Finalize方法.在Finalize方法被调用之后,它才算真正的死亡 ...

  5. 【转】.net框架读书笔记---CLR内存管理\垃圾收集(二)

    前几天学习了CLR垃圾收集原理和基本算法,但是那些是仅仅相对于托管堆而言的,任何非托管资源的类型,例如文件.网络资源等,都必须支持一种称为终止化(finalization)的操作. 终止化 终止化操作 ...

  6. .net框架读书笔记---CLR内存管理\垃圾收集(二)

    前几天学习了CLR垃圾收集原理和基本算法,但是那些是仅仅相对于托管堆而言的,任何非托管资源的类型,例如文件.网络资源等,都必须支持一种称为终止化(finalization)的操作. 终止化 终止化操作 ...

  7. 【转】.net框架读书笔记---CLR内存管理\垃圾收集(七)

    编程控制垃圾收集器 System.GC类型为应用程序提供了直接控制垃圾收集器的一些方法,可以通过GC.MaxGeneration来查询托管堆支持的最大代龄,目前为2. 通过下面方法执行垃圾收集器 GC ...

  8. 《代码的未来》读书笔记:内存管理与GC那点事儿

    一.内存是有限的 近年来,我们的电脑内存都有好几个GB,也许你的电脑是4G,他的电脑是8G,公司服务器内存是32G或者64G.但是,无论内存容量有多大,总归不是无限的.实际上,随着内存容量的增加,软件 ...

  9. 《Linux内核设计与实现》读书笔记(12)--- 内存管理(2)

    6.slab层 为了便于数据的频繁分配和回收,Linux内核提供了slab层(也就是所谓的slab分配器).slab分配器扮演了通用数据结构缓存层的角色. slab层把不同的对象划分为所谓高速缓存(c ...

最新文章

  1. IIS初始化(预加载),解决第一次访问慢,程序池被回收问题
  2. linux rsyslog 系统日志转发
  3. 解决navicate 连接mysql数据库中文乱码的问题
  4. OpenGL交互——菜单控制(基础教程)
  5. angr学习笔记(3)
  6. 交换两个整形变量的数值
  7. python倒三角形粉色填充笔的形状海龟_Python001-Turtle(海龟绘图)详解
  8. C语言学习一个月后感想
  9. 分苹果(信息学奥赛一本通-T1081)
  10. iPhone 14或让果粉再度“梦碎”:屏幕指纹和120Hz高刷屏都没了
  11. 数据结构(字符串)—— 两字符串前后缀相等
  12. mysql覆盖索引和回表
  13. 球形天空盒php,unity3d天空盒
  14. 软件开发常见的软件系统总结
  15. Python: PS 滤镜--碎片特效
  16. 外贸常用术语_常见国际贸易专业术语有哪些?
  17. 关于视频播放的断点续传实现(.NET)
  18. ϵ-greedy Policies
  19. 橡胶密封圈的作用和优点
  20. 数据库建模三步骤:概念模型-逻辑模型-物理模型

热门文章

  1. 【Makefile由浅入深完全学习记录4】变量和不同的赋值方式
  2. SQL Server执行计划那些事儿(3)——书签查找
  3. Java+Jmeter接口测试
  4. java实例练习——基于TCP/IP协议的多客户端通信
  5. MySQL中order by中关于NULL值的排序问题
  6. Java——容器(泛型)
  7. [翻译] 学习iOS开发的建议:如何从菜鸟到专家
  8. 关于递归函数,非递归函数中引用传参的问题
  9. php全局cors,PHP开启CORS - slagga的个人页面 - OSCHINA - 中文开源技术交流社区
  10. java se程序设计课后答案,JAVA SE程序设计及实践