zoukankan      html  css  js  c++  java
  • C#使用throw和throw ex的区别(转)

    使用throw和throw ex的区别

    之前,在使用异常捕获语句try...catch...throw语句时,一直没太留意几种用法的区别,前几天调试程序时无意中了解到几种使用方法是有区别的,网上一查,还真是,主要是区别在堆栈信息的起始点不同。

    总结如下:

    我们都知道,C#中使用throw和throw ex抛出异常,但二者是有区别的。

    在C#中推荐使用throw;来抛出异常;throw ex;会将到现在为止的所有信息清空,认为你catch到的异常已经被处理了,只不过处理过程中又抛出新的异常,从而找不到真正的错误源。

    throw的用法主要有以下几种:

    第一种(不推荐使用,可惜很多人都一直这么用的,包括俺,嘻嘻),这样适用会吃掉原始异常点,重置堆栈中的异常起始点:

    1.  
      try
    2.  
      {
    3.  
      }
    4.  
      catch (Exception ex)
    5.  
      {
    6.  
      throw ex;
    7.  
      }

    第二种,可追溯到原始异常点,不过编译器会警告,定义的ex未有使用:

    1.  
      try
    2.  
      {
    3.  
      }
    4.  
      catch (Exception ex)
    5.  
      {
    6.  
      throw;
    7.  
      }

    第三种,不带异常参数的,这个同第二种其实一样,可捕获所有类型的异常,IDE不会告警:

    1.  
      try
    2.  
      {
    3.  
      }
    4.  
      catch
    5.  
      {
    6.  
      throw;
    7.  
      }

    其实第二种和第三种用法,书上也是不建议使用的,一般要从小粒度的异常捕获开始,采用多个catch语句,大家就见仁见智吧。

    第四种:经过对异常重新包装,但是会保留原始异常点信息。推荐使用

    1.  
      try
    2.  
      {
    3.  
      }
    4.  
      catch (Exception ex)
    5.  
      {
    6.  
      throw new Exception("经过进一步包装的异常", ex);
    7.  
      }

    下面用个例子来加以说明:

    1.  
      class Program
    2.  
      {
    3.  
      /// <summary>
    4.  
      /// 入口方法
    5.  
      /// </summary>
    6.  
      public static void Main()
    7.  
      {
    8.  
      ExceptionClass ec = new ExceptionClass();
    9.  
       
    10.  
      try
    11.  
      {
    12.  
      ec.ExceptionThrow1();
    13.  
      }
    14.  
      catch (Exception ex)
    15.  
      {
    16.  
      Console.WriteLine(ex.ToString());
    17.  
      }
    18.  
       
    19.  
      Console.WriteLine("---------------------------------------------------------------------");
    20.  
       
    21.  
      try
    22.  
      {
    23.  
      ec.ExceptionThrow2();
    24.  
      }
    25.  
      catch (Exception ex)
    26.  
      {
    27.  
      Console.WriteLine(ex.ToString());
    28.  
      }
    29.  
       
    30.  
      Console.WriteLine("---------------------------------------------------------------------");
    31.  
       
    32.  
      try
    33.  
      {
    34.  
      ec.ExceptionThrow3();
    35.  
      }
    36.  
      catch (Exception ex)
    37.  
      {
    38.  
      Console.WriteLine(ex.ToString());
    39.  
      }
    40.  
       
    41.  
      Console.WriteLine("---------------------------------------------------------------------");
    42.  
       
    43.  
      try
    44.  
      {
    45.  
      ec.ExceptionThrow4();
    46.  
      }
    47.  
      catch (Exception ex)
    48.  
      {
    49.  
      Console.WriteLine(ex.ToString());
    50.  
      }
    51.  
       
    52.  
      Console.WriteLine("---------------------------------------------------------------------");
    53.  
       
    54.  
      Console.ReadKey();
    55.  
      }
    56.  
      }
    57.  
       
    58.  
      /// <summary>
    59.  
      /// 该Class用来测试异常抛出时相关上下文栈的调用情况
    60.  
      /// </summary>
    61.  
      public class ExceptionClass
    62.  
      {
    63.  
      /// <summary>
    64.  
      /// 抛出异常方法
    65.  
      /// </summary>
    66.  
      public void ExceptionThrow1()
    67.  
      {
    68.  
      try
    69.  
      {
    70.  
      // 调用原始异常抛出方法来抛出异常
    71.  
      this.ExceptionMethod();
    72.  
      }
    73.  
      catch (Exception ex)
    74.  
      {
    75.  
      throw ex;
    76.  
      }
    77.  
      }
    78.  
       
    79.  
      /// <summary>
    80.  
      /// 抛出异常方法1
    81.  
      /// </summary>
    82.  
      public void ExceptionThrow2()
    83.  
      {
    84.  
      try
    85.  
      {
    86.  
      this.ExceptionMethod();
    87.  
      }
    88.  
      catch (Exception ex)
    89.  
      {
    90.  
      throw;
    91.  
      }
    92.  
      }
    93.  
       
    94.  
      /// <summary>
    95.  
      /// 抛出异常方法2
    96.  
      /// </summary>
    97.  
      public void ExceptionThrow3()
    98.  
      {
    99.  
      try
    100.  
      {
    101.  
      this.ExceptionMethod();
    102.  
      }
    103.  
      catch
    104.  
      {
    105.  
      throw;
    106.  
      }
    107.  
      }
    108.  
       
    109.  
      /// <summary>
    110.  
      /// 抛出异常方法3
    111.  
      /// </summary>
    112.  
      public void ExceptionThrow4()
    113.  
      {
    114.  
      try
    115.  
      {
    116.  
      this.ExceptionMethod();
    117.  
      }
    118.  
      catch (Exception ex)
    119.  
      {
    120.  
      throw new Exception("经过进一步包装的异常", ex);
    121.  
      }
    122.  
      }
    123.  
       
    124.  
      /// <summary>
    125.  
      /// 原始异常抛出方法
    126.  
      /// </summary>
    127.  
      private void ExceptionMethod()
    128.  
      {
    129.  
      throw new DivideByZeroException();
    130.  
      }
    131.  
      }

    运行结果如下:

    从运行的结果可以看到,第一种用法已经吃掉了原始异常信息。而其它3种用法都可以追溯到原始异常,推荐使用第四种用法,希望大家能了解这些细微的差别,享受Coding的乐趣吧。

  • 相关阅读:
    程序中的对话框应用(2)- ”另存为“对话框
    程序中的对话框应用(1)- ”打开“对话框
    Delphi常见报错
    用户界面设计(7)- 窗体上的状态栏应用(StatusBar)
    用户界面设计(6)- 窗体上的工具栏应用(ToolBar)
    用户界面设计(5)- 窗体上菜单的应用
    用户界面设计(4)- 窗体的控制
    用户界面设计(3)- 窗体的主要方法
    Delphi的类和对象(十二)- (TObject、TPersistent、TComponent、TControl、TWinControl、TCustomControl、TGraphicControl、TInterfacedObject)简单介绍
    安装 Visual Stuidio 2010 失败
  • 原文地址:https://www.cnblogs.com/macT/p/11395350.html
Copyright © 2011-2022 走看看