让一个例外冒泡
本文关键字:一个 | 更新日期: 2023-09-27 18:01:12
如何正确地让异常冒泡?
如果我在调用方法时使用 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;
}
...
}
是的,这两种方法具有几乎相同的效果; 重新抛出将展开异常的堆栈 - 这意味着堆栈帧"低于"将丢弃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
...
}
首先,您应该将using
块与资源一起使用,因为这将负责正确关闭资源。第二个示例几乎毫无用处,因为您不会在异常处理程序中执行任何工作。您应该删除它,或者将其包装在另一个异常中以添加一些信息。
是的,结果是一样的。
但是,如果在读取时出现错误,两者都会导致未关闭的流。您应该使用using
块或try ... finally
来确保流已关闭:
using (TextReader tr2 = new StreamReader(nfilepath)) {
resultN = tr2.ReadLine();
}
请注意,此代码中没有Close
。using
块将处置StreamReader
,这将关闭流。
using
块被编译成一个try ... finally
,它使用它来确保始终释放StreamReader
,但异常将冒泡到调用方法。
我建议你使用你的第一个例子,包括这些更改:
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}
您可能希望在记录异常后重新引发异常,因为您没有从错误中进行任何实际恢复。