⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 《_net编程先锋c#》第七章 异常处理_c#语言_网络教程.htm

📁 最近在研究c#
💻 HTM
📖 第 1 页 / 共 2 页
字号:
            和 catch。try包含可能会产生异常的语句,而catch处理一个异常,如果有异常存在的话。清单7.3 用try 和 
            catch为OverflowException 实现异常处理。</P><P>清单7.3 捕获由Factorial 
            Calculation引发的OverflowException 异常</P><P>1: using 
            System;<BR>2: <BR>3: class Factorial<BR>4: {<BR>5: public static 
            void Main(string[] args)<BR>6: {<BR>7: long nFactorial = 1, 
            nCurDig=1;<BR>8: long nComputeTo = Int64.Parse(args[0]);<BR>9: 
            <BR>10: try<BR>11: {<BR>12: checked<BR>13: {<BR>14: for (;nCurDig 
            &lt;= nComputeTo; nCurDig++)<BR>15: nFactorial *= nCurDig;<BR>16: 
            }<BR>17: }<BR>18: catch (OverflowException oe)<BR>19: {<BR>20: 
            Console.WriteLine("Computing {0} caused an overflow exception", 
            nComputeTo);<BR>21: return;<BR>22: }<BR>23: <BR>24: 
            Console.WriteLine("{0}! is {1}",nComputeTo, nFactorial);<BR>25: 
            }<BR>26: }&lt;/P&gt;&lt;P&gt;为了说明清楚,我扩展了某些代码段,而且我也保证异常是由checked 
            语句产生的,甚至当你忘记了编译器设置时。<BR>正如你所见,异常处理并不麻烦。你所有要做的是:在try语句中包含容易产生异常的代码,接着捕获异常,该异常在这个例子中是OverflowException类型。无论一个异常什么时候被引发,在catch段里的代码会注意进行适当的处理。<BR>如果你不事先知道哪一种异常会被预期,而仍然想处于安全状态,简单地忽略异常的类型。&lt;/P&gt;&lt;P&gt;try<BR>{<BR>...<BR>}<BR>catch<BR>{<BR>...<BR>}&lt;/P&gt;&lt;P&gt;但是,通过这个途径,你不能获得对异常对象的访问,而该对象含有重要的出错信息。一般化异常处理代码象这样:&lt;/P&gt;&lt;P&gt;try<BR>{<BR>...<BR>}<BR>catch(System.Exception 
            e)<BR>{<BR>...<BR>}&lt;/P&gt;&lt;P&gt;注意,你不能用ref或out 修饰符传递 e 
            对象给一个方法,也不能赋给它一个不同的值。&lt;/P&gt;&lt;P&gt;7.2.2 使用 try 和 finally 
            清除异常<BR>如果你更关心清除而不是错误处理, try 和 finally 会获得你的喜欢。它不仅抑制了出错消息,而且所有包含在 
            finally 块中的代码在异常被引发后仍然会被执行。<BR>尽管程序不正常终止,但你还可以为用户获取一条消息,如清单 7.4 
            所示。&lt;/P&gt;&lt;P&gt;清单 7.4 在finally 语句中处理异常&lt;/P&gt;&lt;P&gt;1: 
            using System;<BR>2: <BR>3: class Factorial<BR>4: {<BR>5: public 
            static void Main(string[] args)<BR>6: {<BR>7: long nFactorial = 1, 
            nCurDig=1;<BR>8: long nComputeTo = Int64.Parse(args[0]);<BR>9: bool 
            bAllFine = false;<BR>10: <BR>11: try<BR>12: {<BR>13: checked<BR>14: 
            {<BR>15: for (;nCurDig &lt;= nComputeTo; nCurDig++)<BR>16: 
            nFactorial *= nCurDig;<BR>17: }<BR>18: bAllFine = true;<BR>19: 
            }<BR>20: finally<BR>21: {<BR>22: if (!bAllFine)<BR>23: 
            Console.WriteLine("Computing {0} caused an overflow exception", 
            nComputeTo);<BR>24: else<BR>25: Console.WriteLine("{0}! is 
            {1}",nComputeTo, nFactorial);<BR>26: }<BR>27: }<BR>28: 
            }&lt;/P&gt;&lt;P&gt;通过检测该代码,你可能会猜到,即使没有引发异常处理,finally也会被执行。这是真的——在finally中的代码总是会被执行的,不管是否具有异常条件。为了举例说明如何在两种情况下提供一些有意义的信息给用户, 
            我引进了新变量bAllFine。bAllFine告诉finally 
            语段,它是否是因为一个异常或者仅是因为计算的顺利完成而被调用。<BR>作为一个习惯了SEH程序员,你可能会想,是否有一个与__leave 
            语句等价的语句,该语句在C++中很管用。如果你还不了解,在C++中的__leave 语句是用来提前终止 try 
            语段中的执行代码,并立即跳转到finally 语段 。<BR>坏消息, C# 中没有__leave 语句。但是,在清单 7.5 
            中的代码演示了一个你可以实现的方案。&lt;/P&gt;&lt;P&gt;清单 7.5 从 try语句 跳转到finally 
            语句&lt;/P&gt;&lt;P&gt;1: using System;<BR>2: <BR>3: class 
            JumpTest<BR>4: {<BR>5: public static void Main()<BR>6: {<BR>7: 
            try<BR>8: {<BR>9: Console.WriteLine("try");<BR>10: goto 
            __leave;<BR>11: }<BR>12: finally<BR>13: {<BR>14: 
            Console.WriteLine("finally");<BR>15: }<BR>16: <BR>17: 
            __leave:<BR>18: Console.WriteLine("__leave");<BR>19: }<BR>20: 
            }&lt;/P&gt;&lt;P&gt;<BR>当这个应用程序运行时,输出结果为&lt;/P&gt;&lt;P&gt;try<BR>finally<BR>__leave&lt;/P&gt;&lt;P&gt;一个 
            goto 语句不能退出 一个finally 语段。甚至把 goto 语句放在 try 语句 段中,还是会立即返回控制到 finally 
            语段。因此,goto 只是离开了 try 语段并跳转到finally 语段。直到 finally 
            中的代码完成运行后,才能到达__leave 标签。按这种方式,你可以模仿在SEH中使用的的__leave 
            语句。<BR>顺便地,你可能怀疑goto 语句被忽略了,因为它是try 语句中的最后一条语句,并且控制自动地转移到了 finally 
            。为了证明不是这样,试把goto 语句放到Console.WriteLine 
            方法调用之前。尽管由于不可到达代码你得到了编译器的警告,但是你将看到goto语句实际上被执行了,且没有为 try 
            字符串产生的输出。&lt;/P&gt;&lt;P&gt;7.2.3 
            使用try-catch-finally处理所有异常<BR>应用程序最有可能的途径是合并前面两种错误处理技术——捕获错误、清除并继续执行应用程序。所有你要做的是在出错处理代码中使用 
            try 、catch 和 finally语句。清单 7.6 显示了处理零除错误的途径。&lt;/P&gt;&lt;P&gt;清单 7.6 
            实现多个catch 语句&lt;/P&gt;&lt;P&gt;1: using System;<BR>2: <BR>3: class 
            CatchIT<BR>4: {<BR>5: public static void Main()<BR>6: {<BR>7: 
            try<BR>8: {<BR>9: int nTheZero = 0;<BR>10: int nResult = 10 / 
            nTheZero;<BR>11: }<BR>12: catch(DivideByZeroException divEx)<BR>13: 
            {<BR>14: Console.WriteLine("divide by zero occurred!");<BR>15: 
            }<BR>16: catch(Exception Ex)<BR>17: {<BR>18: Console.WriteLine("some 
            other exception");<BR>19: }<BR>20: finally<BR>21: {<BR>22: }<BR>23: 
            }<BR>24: }&lt;/P&gt;&lt;P&gt;这个例子的技巧为,它包含了多个catch 
            语句。第一个捕获了更可能出现的DivideByZeroException异常,而第二个catch语句通过捕获普通异常处理了所有剩下来的异常。<BR>你肯定总是首先捕获特定的异常,接着是普通的异常。如果你不按这个顺序捕获异常,会发生什么事呢?清单7.7中的代码有说明。&lt;/P&gt;&lt;P&gt;清单7.7 
            顺序不适当的 catch 语句&lt;/P&gt;&lt;P&gt;1: try<BR>2: {<BR>3: int nTheZero 
            = 0;<BR>4: int nResult = 10 / nTheZero;<BR>5: }<BR>6: 
            catch(Exception Ex)<BR>7: {<BR>8: Console.WriteLine("exception " + 
            Ex.ToString());<BR>9: }<BR>10: catch(DivideByZeroException 
            divEx)<BR>11: {<BR>12: Console.WriteLine("never going to see 
            that");<BR>13: 
            }&lt;/P&gt;&lt;P&gt;<BR>编译器将捕获到一个小错误,并类似这样报告该错误:<BR>wrongcatch.cs(10,9): 
            error CS0160: A previous catch clause already <BR>catches all 
            exceptions of this or a super type 
            ('System.Exception')&lt;/P&gt;&lt;P&gt;最后,我必须告发CLR异常与SEH相比时的一个缺点(或差别):没有 
            EXCEPTION_CONTINUE_EXECUTION标识符的等价物,它在SEH异常过滤器中很有用。基本上,EXCEPTION_CONTINUE_EXECUTION 
            允许你重新执行负责异常的代码片段。在重新执行之前,你有机会更改变量等。我个人特别喜欢的技术为,使用访问违例异常,按需要实施内存分配。&lt;/P&gt;&lt;P&gt;<BR>7.3 
            引发异常<BR>当你必须捕获异常时,其他人首先必须首先能够引发异常。而且,不仅其他人能够引发,你也可以负责引发。其相当简单:&lt;/P&gt;&lt;P&gt;throw 
            new ArgumentException("Argument can't be 5");<BR>你所需要的是throw 
            语句和一个适当的异常类。我已经从表7.1提供的清单中选出一个异常给这个例子。&lt;/P&gt;&lt;P&gt;表 7.1 
            Runtime提供的标准异常&lt;/P&gt;&lt;P&gt;<BR>异常类型 
            描述&lt;/P&gt;&lt;P&gt;Exception 所有异常对象的基类<BR>SystemException 
            运行时产生的所有错误的基类<BR>IndexOutOfRangeException 
            当一个数组的下标超出范围时运行时引发<BR>NullReferenceException 
            当一个空对象被引用时运行时引发<BR>InvalidOperationException 
            当对方法的调用对对象的当前状态无效时,由某些方法引发<BR>ArgumentException 
            所有参数异常的基类<BR>ArgumentNullException 
            在参数为空(不允许)的情况下,由方法引发<BR>ArgumentOutOfRangeException 
            当参数不在一个给定范围之内时,由方法引发<BR>InteropException 
            目标在或发生在CLR外面环境中的异常的基类<BR>ComException 包含COM 
            类的HRESULT信息的异常<BR>SEHException 封装win32 
            结构异常处理信息的异常&lt;/P&gt;&lt;P&gt;然而,在catch语句的内部,你已经有了随意处置的异常,就不必创建一个新异常。可能在表7.1 
            中的异常没有一个符合你特殊的要求——为什么不创建一个新的异常?在即将要学到小节中,都涉及到这两个话题。&lt;/P&gt;&lt;P&gt;7.3.1 
            重新引发异常<BR>当处于一个catch 
            语句的内部时,你可能决定引发一个目前正在再度处理的异常,留下进一步的处理给一些外部的try-catch 语句。该方法的例子如 
            清单7.8所示。&lt;/P&gt;&lt;P&gt;清单 7.8 重新引发一个异常&lt;/P&gt;&lt;P&gt;1: 
            try<BR>2: {<BR>3: checked<BR>4: {<BR>5: for (;nCurDig &lt;= 
            nComputeTo; nCurDig++)<BR>6: nFactorial *= nCurDig;<BR>7: }<BR>8: 
            }<BR>9: catch (OverflowException oe)<BR>10: {<BR>11: 
            Console.WriteLine("Computing {0} caused an overflow exception", 
            nComputeTo);<BR>12: throw;<BR>13: 
            }&lt;/P&gt;&lt;P&gt;注意,我不必规定所声明的异常变量。尽管它是可选的,但你也可以这样写:<BR>throw 
            oe;<BR>现在有时还必须留意这个异常。&lt;/P&gt;&lt;P&gt;7.3.2 
            创建自己的异常类<BR>尽管建议使用预定义的异常类,但对于实际场合,创建自己的异常类可能会方便。创建自己的异常类,允许你的异常类的使用者根据该异常类采取不同的手段。<BR>在清单 
            7.9 中出现的异常类 
            MyImportantException遵循两个规则:第一,它用Exception结束类名。第二,它实现了所有三个被推荐的通用结构。你也应该遵守这些规则。<BR>清单 
            7.9 实现自己的异常类 MyImportantException&lt;/P&gt;&lt;P&gt;1: using 
            System;<BR>2: <BR>3: public class 
            MyImportantException:Exception<BR>4: {<BR>5: public 
            MyImportantException()<BR>6: :base() {}<BR>7: <BR>8: public 
            MyImportantException(string message)<BR>9: :base(message) {}<BR>10: 
            <BR>11: public MyImportantException(string message, Exception 
            inner)<BR>12: :base(message,inner) {}<BR>13: }<BR>14: <BR>15: public 
            class ExceptionTestApp<BR>16: {<BR>17: public static void 
            TestThrow()<BR>18: {<BR>19: throw new 
            MyImportantException("something bad has happened.");<BR>20: }<BR>21: 
            <BR>22: public static void Main()<BR>23: {<BR>24: try<BR>25: 
            {<BR>26: ExceptionTestApp.TestThrow();<BR>27: }<BR>28: catch 
            (Exception e)<BR>29: {<BR>30: Console.WriteLine(e);<BR>31: }<BR>32: 
            }<BR>33: }&lt;/P&gt;&lt;P&gt;正如你所看到的,MyImportantException 
            异常类不能实现任何特殊的功能,但它完全基于System.Exception类。程序的剩余部分测试新的异常类,给System.Exception 
            类使用一个catch 
            语句。<BR>如果没有特殊的实现而只是给MyImportantException定义了三个构造函数,创建它又有什么意义呢?它是一个重要的类型——你可以在catch语句中使用它,代替更为普通的异常类。可能引发你的新异常的客户代码可以按规定的catch代码发挥作用。<BR>当使用自己的名字空间编写一个类库时,也要把异常放到该名字空间。尽管它并没有出现在这个例子中,你还是应该使用适当的属性,为扩展了的错误信息扩充你的异常类。&lt;/P&gt;&lt;P&gt;7.4 
            异常处理的“要”和“不要” 
            <BR>作为最后的忠告之语,这里是对异常引发和处理所要做和不要做的清单:<BR>。当引发异常时,要提供有意义的文本。<BR>。要引发异常仅当条件是真正异常;也就是当一个正常的返回值不满足时。<BR>。如果你的方法或属性被传递一个坏参数,要引发一个ArgumentException异常。<BR>。当调用操作不适合对象的当前状态时,要引发一个 
            InvalidOperationException异常。<BR>。要引发最适合的异常。<BR>。要使用链接异常,它们允许你跟踪异常树。<BR>。不要为正常或预期的错误使用异常。<BR>。不要为流程的正常控制使用异常。<BR>。不要在方法中引发 
            NullReferenceException或IndexOutOfRangeException异常。&lt;/P&gt;&lt;P&gt;7.5 
            小结<BR>这一章由介绍溢出校验开始。你可以使用编译器开关(默认是关),使整个应用程序允许或禁止溢出校验。如果需要微调控制,你可以使用校验和非校验语句,它允许你使用或不使用溢 
            <BR></TD></TR>
        <TR>
          <TD vAlign=top align=justify>
            <DIV class=adsense id=ad003>
            <P>&nbsp;</P></DIV></TD></TR>
        <TR>
          <TD colSpan=3 height=12>
            <LI>上一篇文章: <A class=LinkPrevArticle 
            title="文章标题:dotNET C# Programmer’s Guide to the Win32 API (Win32 API 声明C#版)&#13;&#10;作&nbsp;&nbsp;&nbsp;&nbsp;者:佚名&#13;&#10;更新时间:2006-5-8 14:35:32" 
            href="http://www.qostudy.org/pr/Article/aspnet/c/200605/16912.html">dotNET&nbsp;C#&nbsp;Programmer’s&nbsp;Guide&nbsp;to&nbsp;the&nbsp;Win32&nbsp;API&nbsp;(Win32&nbsp;API&nbsp;声明C#版)</A><BR>
            <LI>下一篇文章: <A class=LinkNextArticle 
            title="文章标题:《.net编程先锋C#》第六章 控制语句&#13;&#10;作&nbsp;&nbsp;&nbsp;&nbsp;者:佚名&#13;&#10;更新时间:2006-5-8 14:35:32" 
            href="http://www.qostudy.org/pr/Article/aspnet/c/200605/16914.html">《.net编程先锋C#》第六章&nbsp;控制语句</A></LI></TD></TR></TBODY></TABLE></DIV></TD></TR>
  <TR>
    <TD width="100%">
      <P align=right> </P></TD></TR></TBODY></TABLE>
<SCRIPT src="《_net编程先锋C#》第七章 异常处理_C#语言_网络教程.files/count.htm" 
type=text/javascript></SCRIPT>

<TABLE style="BORDER-COLLAPSE: collapse" height=55 cellPadding=0 width=760 
border=0>
  <TBODY>
  <TR>
    <TD vAlign=bottom height=26>
      <P align=left>Copyright Qostudy&copy; 2002-2006 All Rights Reserved 
  网络教程</P></TD></TR>
  <TR>
    <TD 
    style="BORDER-TOP: #a43232 1px solid; BORDER-LEFT-WIDTH: 1px; BORDER-BOTTOM-WIDTH: 1px; BORDER-RIGHT-WIDTH: 1px">
      <P align=left>电信备案许可证 京ICP备02003422号 <A 
      href="http://www.qostudy.org/pr/sitemap/Article1.htm">SiteMap</A>&nbsp;
      <SCRIPT language=javascript 
      src="《_net编程先锋C#》第七章 异常处理_C#语言_网络教程.files/366882.js" 
      type=text/javascript></SCRIPT>
       <NOSCRIPT><A href="http://www.51.la/?366882" target=_blank><IMG 
      style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none" 
      alt=我要啦免费统计 
      src="《_net编程先锋C#》第七章 异常处理_C#语言_网络教程.files/s.htm"></A></NOSCRIPT></P></TD></TR></TBODY></TABLE><!-- Powered by: PowerEasy 2005 --></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -