.Net组件程序设计之对象生命周期
是CLR管理着垃圾回收器,垃圾回收器监控着托管堆,而我们使用的对象以及系统启动是所需要的一些必备的对象信息都存在于托管堆上,CLR会维护着一个列表(对象引用信息列表). 这个列表里存放的信息就是对应着托管堆中所有对象的信息(引用、被引用信息)每当使用一个新的对象或者是改变一个现有对象的引用CLR都会更新 对象引用信息列表。那么回收器一般什么时候调用呢?
垃圾回收器大多数是在托管堆耗尽的情况下被触发使用 ,也可以通过代码来调用(下面会讲到).
在垃圾回收器调用的时候,会从(对象引用信息列表)开始遍历查看每个对象是否能够到达客户端(使用这些对象的应用程序),如果能够到达则这个对象就被标记可到达并且跳过它(查看对象是否有引用),继续的遍历下面,而且被标记的对象所引用的对象将不会被再次检查。当检查到对象没有引用这些对象的时候,则会回收这些对象,并且进行空间压缩,修改那些有引用对象的地址进行空间压缩。
在.NET中给我们提供了IDispose接口就是用来释放资源的,看一段示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<code> </code><code>1 </code><code>public</code> <code>interface</code> <code>IMyinterface</code>
<code> </code><code>2 {</code>
<code> </code><code>3 </code><code>void</code> <code>DoSomeThing();</code>
<code> </code><code>4 }</code>
<code> </code><code>5 </code><code>public</code> <code>class</code> <code>StydyClass:IMyinterface,IDisposable</code>
<code> </code><code>6 {</code>
<code> </code><code>7 </code><code>public</code> <code>void</code> <code>Dispose()</code>
<code> </code><code>8 {</code>
<code> </code><code>9 </code><code>//释放资源</code>
<code>10 }</code>
<code>11 </code><code>public</code> <code>void</code> <code>DoSomeThing()</code>
<code>12 {</code>
<code>13 </code><code>//do something</code>
<code>14 }</code>
<code>15 }</code>
看一下客户端调用代码:
<code>1 IMyinterface studyClass = </code><code>new</code> <code>StudyClass();</code>
<code>2 studyClass.DoSomeThing();</code>
<code>3 </code>
<code>4 IDisposable disposable = studyClass </code><code>as</code> <code>IDisposable;</code>
<code>5 </code><code>if</code> <code>(disposable != </code><code>null</code><code>)</code>
<code>6 {</code>
<code>7 disposable.Dispose();</code>
<code>8 }</code>
这种调用方式很安全啊,如果studyClass没有支持IDisposable,as操作符则会返回NULL值,看起来没什么问题, 但是如果客户端对象是共享的,有很多对象在使用它,那究竟由谁准确的来执行IDisposable.Dispose()。 如果在DoSomeThing()函数执行的时候发生一些错误,那么资源还会被释放吗?
C# 支持Using语句,在使用Using语句的时候会帮我们生成一个使用Dispose()方法的try/finally块,当然你的对象必须先支持IDisposable才行。看一下示例代码:
<code>1 </code><code>using</code> <code>(IMyinterface studyClass = </code><code>new</code> <code>StudyClass())</code>
<code>2 {</code>
<code>3 studyClass.DoSomeThing();</code>
<code>4 }</code>
如果这样写,编译是不会通过的,并且会提示你,using语句中使用的类型是必须可以隐式转换为System.IDisposable的。当然了, 也是有办法可以让这样的代码编译通过的,让IMyinterface接口也派生于IDisposable。 这样之后就可以这样来写代码:
<code> </code><code>1 IMyinterface studyClass = </code><code>new</code> <code>StudyClass();</code>
<code> </code><code>2 </code><code>using</code> <code>(studyClass </code><code>as</code> <code>IDisposable)</code>
<code> </code><code>3 {</code>
<code> </code><code>4 studyClass.DoSomeThing();</code>
<code> </code><code>5 }</code>
<code> </code><code>6 </code>
<code> </code><code>7 </code><code>using</code> <code>(StudyClass studyClass = </code><code>new</code> <code>StudyClass())</code>
<code> </code><code>8 {</code>
<code> </code><code>9 studyClass.DoSomeThing();</code>
<code>10 }</code>
以上的书写方式都是可以实现的,上两段代码同等于下面这段代码:
<code> </code><code>1 StudyClass studyClass = </code><code>new</code> <code>StudyClass();</code>
<code> </code><code>2 </code><code>try</code>
<code> </code><code>6 </code><code>finally</code>
<code> </code><code>7 {</code>
<code> </code><code>8 </code><code>if</code> <code>(studyClass != </code><code>null</code><code>)</code>
<code> </code><code>9 {</code>
<code>10 IDisposable dis = studyClass;</code>
<code>11 dis.Dispose();</code>
<code>12 }</code>
<code>13 }</code>
本篇的内容没有很复杂深奥,只是基础的讲解了一下对象的生命周期管理,还有一些深入的知识就不作讲解了,还有的就是我们在面向对象设计的时候,准备对一些重要的使用率较高的对象面向抽象设计的时候,尽量的让抽象对象来实现IDisposable接口,这样的话也不会出现上述内容中的错误信息。
本文转自jinyuan0829 51CTO博客,原文链接:http://blog.51cto.com/jinyuan/1421931,如需转载请自行联系原作者