关于C#中的异常捕捉

一.c#中的异常清单

    

Exception:所有异常对象的基类。
  SystemException:运行时产生的所有错误的基类。
  IndexOutOfRangeException:当一个数组的下标超出范围时运行时引发。
  NullReferenceException:当一个空对象被引用时运行时引发。
  InvalidOperationException:当对方法的调用对对象的当前状态无效时,由某些方法引发。

  ArgumentException:所有参数异常的基类。
  ArgumentNullException:在参数为空(不允许)的情况下,由方法引发。
  ArgumentOutOfRangeException:当参数不在一个给定范围之内时,由方法引发。
  InteropException:目标在或发生在CLR外面环境中的异常的基类。
  ComException:包含COM类的HRESULT信息的异常。
  SEHException:封装Win32结构异常处理信息的异常。
  SqlException:封装了SQL操作异常。

    常见具体的异常对象:

  ArgumentNullException 一个空参数传递给方法,该方法不能接受该参数
  ArgumentOutOfRangeException 参数值超出范围
  ArithmeticException 出现算术上溢或者下溢
  ArrayTypeMismatchException 试图在数组中存储错误类型的对象
  BadImageFormatException 图形的格式错误
  DivideByZeroException 除零异常
  DllNotFoundException 找不到引用的DLL
  FormatException 参数格式错误
  IndexOutOfRangeException 数组索引超出范围
  InvalidCastException 使用无效的类
  InvalidOperationException 方法的调用时间错误
  NotSupportedException 调用的方法在类中没有实现
  NullReferenceException 试图使用一个未分配的引用
  OutOfMemoryException 内存空间不够
  StackOverflowException 堆栈溢出

try catch中尽量使用具体的异常,避免使用system.Exception  

二. 异常处理需要注意的地方

1)Catch和Finally代码应该非常短,而且成功率极高,避免自己又抛出一个异常。否则CLR会终止进程,避免安全漏洞或者不可预知的后果。这个类似于Windows蓝屏,发生了严重的错误,宁愿使系统不可用。

2)Catch块尽量避免直接捕捉异常的基类Exception,而应该捕捉具体的异常类。

三.针对.net未捕获的异常的处理

  未捕获异常从定义上说就是结构化异常处理未能捕获的异常。通俗的讲就是发生在Try Catch块意外的异常。那么是不是我们在Main函数中加一个Try Catch 块就可以捕获全部未捕获异常了呢?答案是否定的。这里面有两种情况无法通过这种方法捕获:

  1.GC产生的异常,

  2. 主线程以外的线程引发的未捕获的异常。这些异常我们往往可以在线程的主函数中用Try Catch 来捕获,但如果系统中使用了外部的组件,或者甚至是.Net 框架自带的一些 系统组件,由这些组件的线程引发的异常,调用代码无法通过Try Catch来捕获。

  鉴于此,我们需要通过一些方法来截获这些未捕获异常,并进行适当处理。

  .Net 的设计者已经考虑到这些问题,并且为我们提供了一个叫 UnhandledExceptionEventHandler 的事件,通过这个事件,我们可以截获未捕获异常,并进行处理

  .net 2.0以后,如果程序发现有未捕获的异常,会终止程序(这个就是造成程序未知crash的原因?),所以使用UnhandledExceptionEventHandler可以记录下程序发生未捕获异常的位置,方便优化程序。

  wpf中的添加方法:

    在app.xaml.cs中添加 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(<自定义的事件处理方法>);

    自定义的事件处理方法如下:

      

        static void UnhandledExceptionEventHandler(object sender, UnhandledExceptionEventArgs e)         
{           
          try{ 
                using (System.IO.FileStream fs = new System.IO.FileStream(@"c:\testme.log", 
                         System.IO.FileMode.Append, System.IO.FileAccess.Write))
 
                { 
                    using (System.IO.StreamWriter w = new System.IO.StreamWriter(fs, 
                             System.Text.Encoding.UTF8))
                    {                 
                          w.WriteLine(e.ExceptionObject);                   
                    }                 
                }             
             }            
           catch             
                {    退出前的处理动作,如保存数据等 }         
  }