本文翻译自stack overflow Why catch and rethrow an exception in C#? - Stack Overflow
在翻译的同时加上个人的理解,如有不对的的方法请指正
问题抛出:
文章C# - Data Transfer Object - CodeProject 中包含了如下的代码片段:
public static string SerializeDTO(DTO dto) {
try {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
catch(Exception ex) {
throw ex;
}
}
上述代码是否是不是等同下面没抓异常的代码?
public static string SerializeDTO(DTO dto) {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
答案是非也,上面第一部分的代码已经把部分异常的堆栈信息给隐藏了
我们可以做一个测试:
在winform 程序中,添加一个button1按钮,然后加上如下逻辑:
TestBp.cs的代码如下:
public class TestBp
{
public void TestThrowThreadException()
{
throw new Exception("测试抛出异常");
}
}
button1的代码逻辑如下:
private void button1_Click(object sender, EventArgs e)
{
try
{
try
{
new TestBp().TestThrowThreadException();
}
catch (Exception ex)
{
throw ex;
}
}
catch (Exception ex)
{
}
}
调试如下:
可以看到,堆栈信息只记录到了Form1,没有记录到真正导致异常的堆栈信息,想要获取真正导致异常的信息,可以把throw ex修改为throw,把button1的代码逻辑如下:
private void button1_Click(object sender, EventArgs e)
{
try
{
try
{
new TestBp().TestThrowThreadException();
}
catch (Exception ex)
{
throw;
}
}
catch (Exception ex)
{
}
}
重新调试,可以看到能获取到详细的异常堆栈信息了
捕获了异常又重新抛出的目的总结有如下理由:
1 可以在catch捕获后,记录日志,就像这个哥们说的那样:
2 根据不同的异常,需要做不同的额外处理,如下:
就好像这个博主编写日志的正确姿势 - .NET西安社区 - 博客园所说的,记录像支付系统的日志,就不能把用户的卡号和密码信息记录到日志中
3 为了释放类似io那样的资源
try
{
//类似IO流的操作,可能会发生异常
}
catch(Exception ex)
{
//记录日志
throw;
}
fianlly
{
//释放类似IO资源
}
上述的代码,catch关键字是可以去掉的,如果不用记录日志,写成这样会更好
try
{
//类似IO流的操作,可能会发生异常
}
fianlly
{
//释放类似IO资源
}