让一个例外冒泡

本文关键字:一个 | 更新日期: 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();
}

请注意,此代码中没有Closeusing块将处置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}

您可能希望在记录异常后重新引发异常,因为您没有从错误中进行任何实际恢复。

相关文章: