100165346.htm
来自「C#高级编程(第三版),顶死你们。。 。up」· HTM 代码 · 共 173 行 · 第 1/3 页
HTM
173 行
<p class="1" style="MARGIN-LEFT: 37.55pt; LINE-HEIGHT: 15pt; FTEL: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">利用运行库强制执行的析构函数,但析构函数的执行是不确定的,而且,由于垃圾收集器的工作方式,它会给运行库增加不可接受的系统开销。</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; LINE-HEIGHT: 15pt; FTEL: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span lang="EN-US">IDisposable</span><span style="FONT-FAMILY: 宋体">接口提供了一种机制,允许类的用户控制释放资源的时间,但需要确保执行</span><span lang="EN-US">Dispose()</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class="MsoNormal" style="LINE-HEIGHT: 16pt"><span style="FONT-FAMILY: 宋体">一般情况下,最好的方法是执行这两种机制,获得这两种机制的优点,克服其缺点。假定大多数程序员都能正确调用</span><span lang="EN-US">Dispose()</span><span style="FONT-FAMILY: 宋体">,实现</span><span lang="EN-US">IDisposable</span><span style="FONT-FAMILY: 宋体">接口,同时把析构函数作为一种安全的机制,以防没有调用</span><span lang="EN-US">Dispose()</span><span style="FONT-FAMILY: 宋体">。下面是一个双重实现的例子:</span></p>
<p class="2" style="MARGIN-TOP: 4.9pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">public class ResourceHolder : IDisposable</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> private bool isDispose </span><span style="FONT-FAMILY: 宋体">=</span><span lang="EN-US"> false;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 32.25pt"><span lang="EN-US">public void Dispose() </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> Dispose(true);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> GC.SuppressFinalize(this); </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> protected virtual void Dispose(bool disposing) </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> if (!isDisposed)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 32.25pt"><span lang="EN-US"> if (disposing) </span></p>
<p class="2" style="TEXT-JUSTIFY: inter-ideograph; MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; TEXT-ALIGN: justify; FTEL: 59.0pt"><span lang="EN-US">{ </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> // Cleanup managed objects by calling their Dispose() methods.</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> // Cleanup unmanaged objects</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> isDisposed=true;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> ~ResourceHolder()</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> Dispose (false);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN-TOP: 0cm; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">}</span></p>
<p class="MsoNormal" style="LINE-HEIGHT: 15pt"><span style="FONT-FAMILY: 宋体">可以看出,</span><span lang="EN-US">Dispose()</span><span style="FONT-FAMILY: 宋体">有第二个</span><span lang="EN-US">protected</span><span style="FONT-FAMILY: 宋体">重载方法,它带一个</span><span lang="EN-US">bool</span><span style="FONT-FAMILY: 宋体">参数,这是真正完成清理工作的方法。</span><span lang="EN-US">Dispose(bool)</span><span style="FONT-FAMILY: 宋体">由析构函数和</span><span lang="EN-US">IDisposable.Dispose()</span><span style="FONT-FAMILY: 宋体">调用。这个方式的重点是确保所有的清理代码都放在一个地方。</span></p>
<p class="MsoNormal" style="LINE-HEIGHT: 15pt"><span style="FONT-FAMILY: 宋体">传递给</span><span lang="EN-US">Dispose(bool)</span><span style="FONT-FAMILY: 宋体">的参数表示</span><span lang="EN-US">Dispose(bool)</span><span style="FONT-FAMILY: 宋体">是由析构函数调用,还是由</span><span lang="EN-US">IDisposable.Dispose()</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.1pt">调用</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -1.1pt">——</span><span lang="EN-US">Dispose(bool)</span><span style="FONT-FAMILY: 宋体">不应从代码的其他地方调用,其原因是:</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; FTEL: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">如果客户调用</span><span lang="EN-US">IDisposable.Dispose()</span><span style="FONT-FAMILY: 宋体">,该客户就指定应清理所有与该对象相关的资源,包括托管和非托管的资源。</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; FTEL: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">如果调用了析构函数,在原则上,所有的资源仍需要清理。但是在这种情况下,析构函数必须由垃圾收集器调用,而且不应访问其他托管的对象,因为我们不再能确定它们的状态了。在这种情况下,最好清理已知的未托管资源,希望引用的托管对象还有析构函数,执行自己的清理过程。</span></p>
<p class="MsoNormal" style="LINE-HEIGHT: 16pt"><span lang="EN-US">isDispose</span><span style="FONT-FAMILY: 宋体">成员变量表示对象是否已被删除,并允许确保不多次删除成员变量。这个简单的方法不是线程安全的,需要调用者确保在同一时刻只有一个线程调用方法。要求客户进行同步是一个合理的假定,在整个</span><span lang="EN-US">.NET</span><span style="FONT-FAMILY: 宋体">类库中反复使用了这个假定</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">例如在集合类中</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">。第</span><span lang="EN-US">15</span><span style="FONT-FAMILY: 宋体">章将讨论线程和同步。</span></p>
<p class="MsoNormal" style="LINE-HEIGHT: 17pt"><span style="FONT-FAMILY: 宋体">最后,</span><span lang="EN-US">IDisposable.Dispose()</span><span style="FONT-FAMILY: 宋体">包含一个对</span><span lang="EN-US">System.GC. </span><span lang="EN-US">SuppressFinalize()</span><span style="FONT-FAMILY: 宋体">方法的调用。</span><span lang="EN-US">SuppressFinalize()</span><span style="FONT-FAMILY: 宋体">方法则告诉垃圾收集器有一个类不再需要调用其析构函数了。因为</span><span lang="EN-US">Dispose()</span><span style="FONT-FAMILY: 宋体">已经完成了所有需要的清理工作,所以析构函数不需要做任何工作。调用</span><span lang="EN-US">SuppressFinalize()</span><span style="FONT-FAMILY: 宋体">就意味着垃圾收集器认为这个对象根本没有析构函数。</span></p></div>
<!-- page -->
<div class="page" style="text-align: center">
<a href="100165345.htm">上一页</a> <a href="index.html">首页</a> <a href="100165347.htm">下一页</a>
</div>
<div style="margin: 0px auto; width: 700px; border: solid 1px #0b5f98;">
<div style="float: left; width: 16px; background-color: #0b5f98; color: White; padding: 1px;">
图书导读
</div>
<div style="float: right; width: 670px; text-align: left; line-height: 16pt; padding-left: 2px">
<!--导读-->
<h1 id="divCurrentNode2" style="color: #b83507; width: 100%; text-align: left; font-size: 12px; padding-left: 2px">当前章节:<a href='100165346.htm'><font color='red'>7.2 释放未托管的资源</font></a></h1>
<div id="divRealteNod2" style="padding-left: 2px">
<div style='float:left;width:49%'>·<a href='100165343.htm'>6.2.2 生成事件</a></div><div style='float:right;width:49%'>·<a href='100165344.htm'>6.3 小结</a></div><div style='float:left;width:49%'>·<a href='100165345.htm'>7.1 后台内存管理</a></div><div style='float:right;width:49%'>·<a href='100165347.htm'>7.3 不安全的代码</a></div><div style='float:left;width:49%'>·<a href='100165348.htm'>7.3.1 指针(1)</a></div><div style='float:right;width:49%'>·<a href='100165349.htm'>7.3.1 指针(2)</a></div></div>
</div>
</div>
</div></div>
</body>
</html>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?