C#入门经典-- 7.2 错误处理

(一)异常
       异常是代码中产生的错误,或者在运行期间由代码调用的函数产生的错误。例如,如果函数的一个字符串参数不是以a开头,就产生一个异常。这并不是严格意义上的函数外部错误,但调用该函数的代码把它看作函数外部错误。

1、try...catch...finally
      C#语言包含结构化异常处理(Structured Execption Handing,SEH)的语法。关键字可以标记出能处理异常的代码和指令,如果发生异常,就使用这些指令处理异常。用于这个目的的三个关键字是try,catch和fianlly。它们都有一个关联的代码块,必须在连续的代码行中使用。其基本结构如下:
      try
      {
          ...
      }
      catch(<exceptionType> e)
      {
         ...
      }
      finally
      {
         ...
      }
也可以只有try块和finally块,而没有catch块,或者有一个try块和好几个catch块。如果有一个或多个catch块,finally块是可选的,否则就是必需的。
      这些代码块的用法如下:

  • try --包含产生异常的代码。
  • catch -- 包含产生异常时要执行的代码。catch块可以使用<exceptionType>,设置为只响应特定的异常类型,以便提供多个catch块。还可以完全省略这个参数,让一般的catch块响应所有的异常。
  • finally -- 包含总是会执行的代码,如果没有产生异常,则在try块之后执行,如果处理了异常,就在catch块后执行,或者在未处理的异常中断应用程序之前执行(此时处理这个块,其原因是存在这个块,否则也可以在这个块的后面放置代码)。
       

       在try的代码中出现异常后,发生的事件依次是:

  • try块在发生异常的地方中断程序的运行。
  • 如果有catch块,就检查该块是否匹配于已发生的异常类型。如果没有catch块,就执行finall块(如果有catch块,就一定要执行finally块)。
  • 如果有catch块,但它与已发生的异常类型不匹配,就检查是否有其他catch块。
  • 如果有catch块匹配于已发生的异常类型,就执行它包含的代码,再执行finally块(如果有)。
  • 如果catch块不匹配于已发生的异常类型,就执行finally块(如果有)。

【示例】
class Program
    {
       static string[] eTypes = {"none","simple","index","nest index"};
       static void Main(string[] args)
       {
           foreach(string eType in eTypes)
           {
               try
               {
                  Console.WriteLine("Main() try block reached.");
                  Console.WriteLine("ThrowException(\"{0}\") called.",eType);
                  ThrowExecption(eType);
                  Console.WriteLine("Main() try block continues.");
               }
               catch(System.IndexOutOfRangeException e)
               {
                   Console.WriteLine("Main() System.IndexOutOfRangeException catch"
                     + " block reached. Message:\n\"{0}\"",e.Message);
               }
               catch
               {
                  Console.WriteLine("Main() general catch block reached.");
               }
               finally
               {
                  Console.WriteLine("Main() finally block reached.");
               }

               Console.WriteLine();
           }

           Console.ReadKey();
       }

       static void ThrowExecption(string execptionType)
       {
           Console.WriteLine("ThrowExecption(\"{0}\") reached.",execptionType);
           switch(execptionType)
           {
               case "none":
                  Console.WriteLine("Not throw an exception.");
                  break;
               case "index":
                  Console.WriteLine("Throwing System.IndexOutOfRangeException.");
                  eTypes[4] = "error";
                  break;
               case "nested index":
                  try
                  {
                      Console.WriteLine("ThrowException(\"nested index\") " +
                                     "try block reached.");
                      Console.WriteLine("ThrowException(\"index\") called");
                      ThrowExecption("index");
                  }
                  catch
                  {
                      Console.WriteLine("ThrowException(\"nested index\") general"
                                + " catch block reached.");
                  }
                  finally
                  {
                      Console.WriteLine("ThrowException(\"nested index\") finally"
                                  + " block reached.");
                  }
                  break;
               case "simple":
                  Console.WriteLine("Throwing System.Exception.");
                  throw new System.Exception();
                 // break;
           }
       }
    }  

2、列出和配置异常
       VS提供了一个对话框,可以检查和编辑可用的异常,该对话框可以使用调试|异常...菜单选项(或者按下Ctrl+D,E)打开。异常按照类别和.NET库命名空间列出。扩展Common Language Runtime Execption选项,再扩展System选项,就可以看到System命名空间中的异常。
       每个异常都可以使用右边的复选框来配置。可以使用第一个选项“引发”中断调试器,即使是对于要处理的异常,也是这样。 第二个选项可以忽略未处理的异常,这样做会对结果有影响。在大多数情况下,这会进入中断模式,所有只需在异常环境下这么做。

3、异常处理的注意事项
       注意,必须在更一般的异常捕获之前为比较特殊的异常提供catch块。如果catch块的顺序错误,应用程序就会编译错误。
       还要注意可以在catch块中产生异常,方法是使用上一个示例中方式,或使用下述表达式:
           throw;
       这个表达式会再次产生catch块处理过的异常。如果以这种方式产生异常,该异常就不会由当前的try...catch...finally块处理,而是由上一级的代码处理(但嵌套结果中的finally块仍会执行)。

posted on 2008-03-25 11:01  清香的功夫茶  阅读(306)  评论(0编辑  收藏  举报