找回密码
 立即注册
首页 业界区 业界 throw和throw ex的区别

throw和throw ex的区别

颜才 2025-5-29 18:58:14
 
之前,在使用异常捕获语句try...catch...throw语句时,一直没太留意几种用法的区别,前几天调试程序时无意中了解到几种使用方法是有区别的,网上一查,还真是,主要是区别在堆栈信息的起始点不同。总结如下:
我们都知道,C#中使用throw和throw ex抛出异常,但二者是有区别的。
在C#中推荐使用throw;来抛出异常;throw ex;会将到现在为止的所有信息清空,认为你catch到的异常已经被处理了,只不过处理过程中又抛出新的异常,从而找不到真正的错误源。
throw的用法主要有以下几种:
 
第一种(不推荐使用,可惜很多人都一直这么用的,包括俺,嘻嘻),这样适用会吃掉原始异常点,重置堆栈中的异常起始点:
1.gif
2.gif
View Code
  1.             try
  2.             {
  3.             }
  4.             catch (Exception ex)
  5.             {
  6.                 throw ex;
  7.             }
复制代码
 
第二种,可追溯到原始异常点,不过编译器会警告,定义的ex未有使用:
3.gif
4.gif
View Code
  1.             try
  2.             {
  3.             }
  4.             catch (Exception ex)
  5.             {
  6.                 throw;
  7.             }
复制代码
 
第三种,不带异常参数的,这个同第二种其实一样,可捕获所有类型的异常,IDE不会告警:
5.gif
6.gif
View Code
  1.             try
  2.             {
  3.             }
  4.             catch
  5.             {
  6.                 throw;
  7.             }
复制代码
 
其实第二种和第三种用法,书上也是不建议使用的,一般要从小粒度的异常捕获开始,采用多个catch语句,大家就见仁见智吧。。。
 
第四种:经过对异常重新包装,但是会保留原始异常点信息。推荐使用。
7.gif
8.gif
View Code
  1.             try
  2.             {
  3.             }
  4.             catch (Exception ex)
  5.             {
  6.                 throw new Exception("经过进一步包装的异常", ex);
  7.             }
复制代码
 
下面用个例子来加以说明:
9.gif
10.gif
View Code
  1.   1         /// <summary>
  2.   2         /// 入口方法
  3.   3         /// </summary>
  4.   4         public static void Main()
  5.   5         {
  6.   6             ExceptionClass ec = new ExceptionClass();
  7.   7
  8.   8             try
  9.   9             {
  10. 10                 ec.ExceptionThrow1();
  11. 11             }
  12. 12             catch (Exception ex)
  13. 13             {
  14. 14                 Console.WriteLine(ex.ToString());
  15. 15             }
  16. 16
  17. 17             Console.WriteLine("---------------------------------------------------------------------");
  18. 18
  19. 19             try
  20. 20             {
  21. 21                 ec.ExceptionThrow2();
  22. 22             }
  23. 23             catch (Exception ex)
  24. 24             {
  25. 25                 Console.WriteLine(ex.ToString());
  26. 26             }
  27. 27
  28. 28             Console.WriteLine("---------------------------------------------------------------------");
  29. 29
  30. 30             try
  31. 31             {
  32. 32                 ec.ExceptionThrow3();
  33. 33             }
  34. 34             catch (Exception ex)
  35. 35             {
  36. 36                 Console.WriteLine(ex.ToString());
  37. 37             }
  38. 38
  39. 39             Console.WriteLine("---------------------------------------------------------------------");
  40. 40
  41. 41             try
  42. 42             {
  43. 43                 ec.ExceptionThrow4();
  44. 44             }
  45. 45             catch (Exception ex)
  46. 46             {
  47. 47                 Console.WriteLine(ex.ToString());
  48. 48             }
  49. 49
  50. 50             Console.WriteLine("---------------------------------------------------------------------");
  51. 51
  52. 52             Console.ReadKey();
  53. 53         }
  54. 54     }
  55. 55
  56. 56     /// <summary>
  57. 57     /// 该Class用来测试异常抛出时相关上下文栈的调用情况
  58. 58     /// </summary>
  59. 59     public class ExceptionClass
  60. 60     {
  61. 61         /// <summary>
  62. 62         /// 抛出异常方法
  63. 63         /// </summary>
  64. 64         public void ExceptionThrow1()
  65. 65         {
  66. 66             try
  67. 67             {
  68. 68                 // 调用原始异常抛出方法来抛出异常
  69. 69                 this.ExceptionMethod();
  70. 70             }
  71. 71             catch (Exception ex)
  72. 72             {
  73. 73                 throw ex;
  74. 74             }
  75. 75         }
  76. 76
  77. 77         /// <summary>
  78. 78         /// 抛出异常方法1
  79. 79         /// </summary>
  80. 80         public void ExceptionThrow2()
  81. 81         {
  82. 82             try
  83. 83             {
  84. 84                 this.ExceptionMethod();
  85. 85             }
  86. 86             catch (Exception ex)
  87. 87             {
  88. 88                 throw;
  89. 89             }
  90. 90         }
  91. 91
  92. 92         /// <summary>
  93. 93         /// 抛出异常方法2
  94. 94         /// </summary>
  95. 95         public void ExceptionThrow3()
  96. 96         {
  97. 97             try
  98. 98             {
  99. 99                 this.ExceptionMethod();
  100. 100             }
  101. 101             catch
  102. 102             {
  103. 103                 throw;
  104. 104             }
  105. 105         }
  106. 106
  107. 107         /// <summary>
  108. 108         /// 抛出异常方法3
  109. 109         /// </summary>
  110. 110         public void ExceptionThrow4()
  111. 111         {
  112. 112             try
  113. 113             {
  114. 114                 this.ExceptionMethod();
  115. 115             }
  116. 116             catch (Exception ex)
  117. 117             {
  118. 118                 throw new Exception("经过进一步包装的异常", ex);
  119. 119             }
  120. 120         }
  121. 121
  122. 122         /// <summary>
  123. 123         /// 原始异常抛出方法
  124. 124         /// </summary>
  125. 125         private void ExceptionMethod()
  126. 126         {
  127. 127             throw new DivideByZeroException();
  128. 128         }
  129. 129    }
复制代码
 
运行结果如下:
11.jpeg

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

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册