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'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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">&nbsp;&nbsp; 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">&nbsp;&nbsp; {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dispose(true);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GC.SuppressFinalize(this); </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; 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">&nbsp;&nbsp; {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; &nbsp;&nbsp;if (!isDisposed)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 32.25pt"><span lang="EN-US">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;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">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 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">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;// Cleanup unmanaged objects</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp; isDisposed=true;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; ~ResourceHolder()</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dispose (false);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 12.5pt; FTEL: 18.45pt"><span lang="EN-US">&nbsp;&nbsp; }</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">&mdash;&mdash;</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'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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>&nbsp;&nbsp;&nbsp;<a href="index.html">首页</a>&nbsp;&nbsp;&nbsp;<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 + -
显示快捷键?