如何正确让异常冒泡?
如果我在调用方法时使用Try-Catch,只是在一个方法中抛出异常而不是试图捕获它?
举例说明:这些方法是否做同样的工作?
示例1:
try
{
MyFileHandlingMethod();
}
catch (IOException ex)
{
string recfilepath = "...
string rectoadd = "RecDateTime=" + DateTime.Now.ToString()+ ...+ex.Message.ToString();
File.AppendAllText(recfilepath, rectoadd);
}
catch (exception)
{
throw;
}
...
MyFileHandlingMethod()
{
...
TextReader tr2 = new StreamReader(nfilepath);
resultN = tr2.ReadLine();
tr2.Close();
...
}
示例2:
try
{
MyFileHandlingMethod();
}
catch (IOException ex)
{
string recfilepath = "...
string rectoadd = "RecDateTime=" + DateTime.Now.ToString()+ ...+ex.Message.ToString();
File.AppendAllText(recfilepath, rectoadd);
}
catch (exception)
{
throw;
}
...
MyFileHandlingMethod()
{
...
try
{
TextReader tr2 = new StreamReader(nfilepath);
resultN = tr2.ReadLine();
tr2.Close();
}
catch (Exception)
{
throw;
}
...
}
答案 0 :(得分:12)
是的,这2种方法几乎效果相同; rethrowing will unwind the stack of the exception - 意味着堆栈帧“低于”throw;
将被丢弃的方法。它们仍将位于堆栈跟踪中,但除非您中断抛出的异常,否则您将无法在调试器中访问其本地变量。
像下面的一个catch / throw块,你没有对异常做任何事情(比如日志记录),是没用的:
catch (Exception)
{
throw;
}
在两个样本中将其移除以进行清理。通常,尽可能避免输入catch
块
并且您的方法有另一个与异常相关的问题,它没有正确释放资源。 tr2.Close();
属于finally
子句,但让编译器使用using() {}
块处理它更容易:
void MyFileHandlingMethod()
{
...
using (TextReader tr2 = new StreamReader(nfilepath))
{
resultN = tr2.ReadLine();
} //tr2.Dispose() inserted automatically here
...
}
答案 1 :(得分:2)
首先,您应该将using
块与资源一起使用,因为这将正确地关闭您的资源。第二个例子几乎没用,因为你在异常处理程序中没有做任何工作。您应该删除它,或将其包装在另一个Exception中以添加一些信息。
答案 2 :(得分:2)
是的,结果是一样的。
但是,如果在读取时出现错误,两者都将导致未关闭的流。您应该使用using
块或try ... finally
来确保流已关闭:
using (TextReader tr2 = new StreamReader(nfilepath)) {
resultN = tr2.ReadLine();
}
请注意,此代码中没有Close
。 using
块会释放StreamReader
,这将关闭流。
using
块被编译为try ... finally
,用于确保始终处置StreamReader
,但异常将冒泡到调用方法。
答案 3 :(得分:1)
我建议您使用第一个示例,并进行以下更改:
try
{
MyFileHandlingMethod();
}
catch (IOException ex)
{
string recfilepath = "...";
string rectoadd = "RecDateTime=" + DateTime.Now.ToString()+ ex.Message.ToString();
File.AppendAllText(recfilepath, rectoadd);
throw; // rethrow the same exception.
}
// no need for second catch}
您可能希望在记录异常后重新抛出异常,因为您没有从错误中进行任何实际的恢复。