100165377.htm
来自「C#高级编程(第三版),顶死你们。。 。up」· HTM 代码 · 共 231 行 · 第 1/3 页
HTM
231 行
<p class="2" style="MARGIN-TOP: 16.35pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US"> try</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> peopleToRing.Open(fileName);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> for (int i=0 ; i<peopleToRing.NPeopleToRing; i++)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> peopleToRing.ProcessNextPerson();</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> Console.WriteLine("All callers processed correctly");</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> catch(FileNotFoundException e)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> Console.WriteLine("The file {0} does not exist", fileName);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 15pt; FTEL: 18.45pt"><span lang="EN-US"> catch(ColdCallFileFormatException e)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 15pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 15pt; FTEL: 18.45pt"><span lang="EN-US"> Console.WriteLine(</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 15pt; FTEL: 18.45pt"><span lang="EN-US"> "The file {0} appears to have been corrupted", fileName);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 15pt; FTEL: 18.45pt"><span lang="EN-US"> Console.WriteLine("Details of problem are: {0}", e.Message);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 15pt; FTEL: 18.45pt"><span lang="EN-US"> if (e.InnerException != null)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 15pt; FTEL: 18.45pt"><span lang="EN-US"> Console.WriteLine(</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 15pt; FTEL: 18.45pt"><span lang="EN-US"> "Inner exception was: {0}", e.InnerException.Message);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 15pt; FTEL: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 15pt; FTEL: 18.45pt"><span lang="EN-US"> catch(Exception e)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> Console.WriteLine("Exception occurred:\n" + e.Message);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> } </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> finally</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> peopleToRing.Dispose();</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> Console.ReadLine();</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; 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"><span style="FONT-FAMILY: 宋体">这段代码基本上是一个循环,处理文件中的人名。开始时,先让用户输入文件名,再实例化一个类的对象</span><span lang="EN-US">ColdCallFileReader</span><span style="FONT-FAMILY: 宋体">,这个类用于处理文件中数据的读取。注意是在第一个</span><span lang="EN-US">try</span><span style="FONT-FAMILY: 宋体">块的外部读取文件<span style="LETTER-SPACING: -1pt">——</span></span><span style="LETTER-SPACING: -1pt"> </span><span style="FONT-FAMILY: 宋体">这是因为这里实例化的变量需要在后面的</span><span lang="EN-US">catch </span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US"> finally</span><span style="FONT-FAMILY: 宋体">块中使用,如果在</span><span lang="EN-US">try</span><span style="FONT-FAMILY: 宋体">块中声明它们,它们在</span><span lang="EN-US">try</span><span style="FONT-FAMILY: 宋体">块的闭合花括号处就出了作用域。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在</span><span lang="EN-US">try</span><span style="FONT-FAMILY: 宋体">块中打开文件</span><span lang="EN-US">(ColdCallFileReader.Open()</span><span style="FONT-FAMILY: 宋体">方法</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">,并循环处理其中所有的人名。</span><span lang="EN-US">ColdCallFileReader.ProcessNextPerson()</span><span style="FONT-FAMILY: 宋体">方法会读取并显示文件中的下一个人名,而</span><span lang="EN-US">ColdCallFileReader.NpeopleToRing</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></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">有</span><span lang="EN-US">3</span><span style="FONT-FAMILY: 宋体">个</span><span lang="EN-US">catch</span><span style="FONT-FAMILY: 宋体">块,其中两个用于处理</span><span lang="EN-US">FileNotFoundException</span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US">ColdCallFileFormatException</span><span style="FONT-FAMILY: 宋体">异常,第三个则用于处理其他</span><span lang="EN-US">.NET</span><span style="FONT-FAMILY: 宋体">错误。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在</span><span lang="EN-US">FileNotFoundException</span><span style="FONT-FAMILY: 宋体">中,我们会为它显示一个信息,注意在这个</span><span lang="EN-US">catch</span><span style="FONT-FAMILY: 宋体">块中,根本不会使用异常实例,原因是这个</span><span lang="EN-US">catch</span><span style="FONT-FAMILY: 宋体">块用于说明应用程序的用户友好性。异常对象一般会包含技术信息,这些技术对开发人员是很有用的,但对于最终用户来说则没有什么用,所以在本例中我们将创建一个更简单的信息。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">对于</span><span lang="EN-US">ColdCallFileFormatException</span><span style="FONT-FAMILY: 宋体">处理程序,我们已经完成了编码,说明了如何提供更完整的技术信息,包括内层异常的细节。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">最后,如果捕获到其他一般异常,就显示一个用户友好信息,而不是让这些异常由</span><span lang="EN-US">.NET</span><span style="FONT-FAMILY: 宋体">运<span style="LETTER-SPACING: 0.1pt">行库处理。注意我们选择不处理派生于</span></span><span lang="EN-US" style="LETTER-SPACING: 0.1pt">System.Exception</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">的异常,因为不直接调用非</span><span lang="EN-US" style="LETTER-SPACING: 0.1pt">.NET</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">的代码。</span></p>
<p class="MsoNormal"><span lang="EN-US">Finally</span><span style="FONT-FAMILY: 宋体">块清理资源。在本例中,是指关闭一些已打开的文件。</span><span lang="EN-US">ColdCallFileReader.Dispose()</span><span style="FONT-FAMILY: 宋体">方法完成了这个任务。</span></p>
<h4 style="FTEL: 21.45pt"><span lang="EN-US">2. </span><span style="FONT-FAMILY: 黑体">抛出用户定义的异常</span></h4>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">下面看看处理文件读取的类的定义,以及抛出用户定义的异常的类</span><span lang="EN-US">ColdCallFileReader</span><span style="FONT-FAMILY: 宋体">。这个类维护一个外部文件连接,所以需要确保它根据第</span><span lang="EN-US">4</span><span style="FONT-FAMILY: 宋体">章有关释放对象的规则,正确地释放。这个类派生于</span><span lang="EN-US">IDisposable</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">首先声明一些变量:</span></p>
<p class="2" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US"> class ColdCallFileReader :IDisposable</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> FileStream fs;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> StreamReader sr;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> uint nPeopleToRing;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> bool isDisposed = false;</span></p>
<p class="2" style="MARGIN-TOP: 0cm; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US"> bool isOpen = false;</span></p>
<p class="MsoNormal"><span lang="EN-US">FileStream </span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US"> StreamReader</span><span style="FONT-FAMILY: 宋体">都在</span><span lang="EN-US">System.IO</span><span style="FONT-FAMILY: 宋体">命名空间中,都是要用于读取文件的基类。</span><span lang="EN-US">FileStream</span><span style="FONT-FAMILY: 宋体">首先连接文件,</span><span lang="EN-US">StreamReader</span><span style="FONT-FAMILY: 宋体">则专门用于读取文本文件,执行方法</span><span lang="EN-US">StreamReader()</span><span style="FONT-FAMILY: 宋体">,该方法读取文件中的一行文本。第</span><span lang="EN-US">31</span><span style="FONT-FAMILY: 宋体">章在深入讨论文件处理时将讨论</span><span lang="EN-US">StreamReader</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class="MsoNormal"><span lang="EN-US" style="LETTER-SPACING: -0.1pt">isDisposed</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.1pt">字</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.3pt">段表示是否调用了</span><span lang="EN-US" style="LETTER-SPACING: -0.3pt">Dispose()</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.3pt">方法,我们选择执行</span><span lang="EN-US" style="LETTER-SPACING: -0.3pt">ColdCallFileReader</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.3pt">,这样,一旦调用了</span><span lang="EN-US" style="LETTER-SPACING: -0.3pt">Dispose()</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.3pt">方法,就不能重新打开文件连接,重新使用对象了。</span><span lang="EN-US" style="LETTER-SPACING: -0.3pt">isOpen</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.3pt">也用于错误检查——</span><span style="LETTER-SPACING: -0.3pt"> </span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.3pt">在本例中,检查</span><span lang="EN-US" style="LETTER-SPACING: -0.3pt">StreamReader</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.3pt">是否连接到打开的文件上</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.2pt">打开文件和读取第一行的过程</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -1pt">——</span><span style="LETTER-SPACING: -1pt"> </span><span style="FONT-FAMILY: 宋体">告诉我们文件中有多少个人名<span style="LETTER-SPACING: -1pt">——</span></span><span style="LETTER-SPACING: -1pt"> </span><span style="FONT-FAMILY: 宋体">由</span><span lang="EN-US">Open()</span><span style="FONT-FAMILY: 宋体">方法来处理:</span></p>
<p class="2" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US"> public void Open(string fileName)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> if (isDisposed)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> throw new ObjectDisposedException("peopleToRing");</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> fs = new FileStream(fileName, FileMode.Open);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> sr = new StreamReader(fs);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> try </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> string firstLine = sr.ReadLine();</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> nPeopleToRing = uint.Parse(firstLine);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> isOpen = true;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> }</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> catch (FormatException e)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> throw new ColdCallFileFormatException(</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> "First line isn\'t an integer", e);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; 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"><span style="FONT-FAMILY: 宋体">与其他</span><span lang="EN-US">ColdCallFileReader</span><span style="FONT-FAMILY: 宋体">方法一样,该方法首先检查在删除对象后,客户机代码是否不正确地调用了它,如果是,就抛出一个预定义的</span><span lang="EN-US">ObjectDisposedException</span><span style="FONT-FAMILY: 宋体">对象。</span><span lang="EN-US">Open()</span><span style="FONT-FAMILY: 宋体">方法也会检查</span><span lang="EN-US">isDisposed</span><span style="FONT-FAMILY: 宋体">字段,看看</span><span lang="EN-US">Dispose()</span><span style="FONT-FAMILY: 宋体">是否已经被调用。因为调用</span><span lang="EN-US">Dispose()</span><span style="FONT-FAMILY: 宋体">会告诉调用者现在已经处理完对象,所以,如果已经调用了</span><span lang="EN-US">Dispose()</span><span style="FONT-FAMILY: 宋体">,就说明有一个试图打开新文件连接的错误。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">接着,这个方法包含前两个内层的</span><span lang="EN-US">try</span><span style="FONT-FAMILY: 宋体">块,其目的是捕获因文件的第一行没有包含一个整数而抛出的错误。如果出现这个问题,</span><span lang="EN-US">.NET</span><span style="FONT-FAMILY: 宋体">运行库就抛出一个</span><span lang="EN-US">FormatException</span><span style="FONT-FAMILY: 宋体">,捕获并转换一个更有意义的异常,表示</span><span lang="EN-US">cold-call</span><span style="FONT-FAMILY: 宋体">文件的格式有问题。注意</span><span lang="EN-US">System.FormatException</span><span style="FONT-FAMILY: 宋体">表示与基本数据类型相关的格式问题</span><span style="FONT-FAMILY: 宋体">,</span><span style="FONT-FAMILY: 宋体">而不是与文件有关</span><span style="FONT-FAMILY: 宋体">,</span><span style="FONT-FAMILY: 宋体">所以在本例中它不是传递回调用例程的一个特别有用的异常。新抛出的异常会被最外层的</span><span lang="EN-US">try</span><span style="FONT-FAMILY: 宋体">块捕获。注意这里不需要清理资源,所以也不需要</span><span lang="EN-US">finally</span><span style="FONT-FAMILY: 宋体">块。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">如果一切正常,就把</span><span lang="EN-US">isOpen</span><span style="FONT-FAMILY: 宋体">字段设置为</span><span lang="EN-US">true</span><span style="FONT-FAMILY: 宋体">,表示现在有一个有效的文件连接,可以从中读取数据。</span></p>
<p class="MsoNormal"><span lang="EN-US">ProcessNextPerson()</span><span style="FONT-FAMILY: 宋体">方法也包含一个内层</span><span lang="EN-US">try</span><span style="FONT-FAMILY: 宋体">块:</span></p>
<p class="2" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US"> public void ProcessNextPerson()</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> {</span></p>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?