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/
签名:成熟是一种明亮而不刺眼的光辉。

浙公网安备 33010602011771号