C#准确抛出异常错误位置
上一年,为了最大程度减小影响,提得最多的词是 "精准防控"。程序异常处理也要做到精准,这样才能节约排查时间,降低分析难度,快速解决问题。我们经常使用try-catch捕捉异常,使用StackTrace来输出具体位置。但在复杂的框架和业务系统中,要注意它的使用方式。下面分别以不同的实例来说明问题。
一、单层捕捉异常
业务逻辑非常简单,代码只有一层(不切实际的想象)。
using System; using System.Windows.Forms; namespace ExceptionTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { try { int a = 10; int b = 0; Console.WriteLine(a / b); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } }
}
}
使用try-catch能轻松捕捉异常位置:17行的b为0,不能当作除数!
二、外层捕捉异常,内层不处理(可用)
实际项目中,往往是对象调用、函数嵌套,为了简便(偷懒),我们在最外层加try-catch,里面不做任何处理。
using System; using System.Windows.Forms; namespace ExceptionTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { try { int a = 10; int b = 0; Divide(a, b); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } public static void Divide(int a,int b) { Console.WriteLine(a / b); } } }
结果也能居然也能定位,这难道就是"无为而治"吗?
三、外层捕捉异常,内部抛出
为了彰显我们有良好的代码习惯,得在内层函数加个try,显得更复杂,似乎才能体现出"水平"。
using System; using System.Windows.Forms; namespace ExceptionTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { try { int a = 10; int b = 0; Divide(a, b); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } public static void Divide(int a, int b) { try { Console.WriteLine(a / b); } catch (Exception ex) { throw; } } } }
结果无法准确定位到29行,而变成了throw所在33行。
四、外层捕捉异常,内层抛出异常
再尝试抛出throw ex看看。
using System; using System.Windows.Forms; namespace ExceptionTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { try { int a = 10; int b = 0; Divide(a, b); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } public static void Divide(int a, int b) { try { Console.WriteLine(a / b); } catch (Exception ex) { throw ex; } } } }
结果还是不能定位。多此一举?
五、外层捕捉异常,内层抛出新异常
在内层抛出一个新异常。
using System; using System.Windows.Forms; namespace ExceptionTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { try { int a = 10; int b = 0; Divide(a, b); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } public static void Divide(int a, int b) { try { Console.WriteLine(a / b); } catch (Exception ex) { throw new Exception(ex.Message); } } } }
六、外层捕捉异常,内层抛出内部异常(推荐)
我们内层抛出new Exception(且包含内部异常),而不是直接抛出Exception。
using System; using System.Windows.Forms; namespace ExceptionTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { try { int a = 10; int b = 0; Divide(a, b); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } public static void Divide(int a, int b) { try { Console.WriteLine(a / b); } catch (Exception ex) { throw new Exception(ex.Message,ex); } } } }
这是我们想要的,每个需要处理异常的函数都需使用 new Exception(且包含内部异常),每个不需要处理异常的函数做也不需要做。
作者:我也是个傻瓜
出处:http://www.cnblogs.com/liweis/
签名:成熟是一种明亮而不刺眼的光辉。