让异常上抛

4
如何正确地让异常上升? 如果我在调用方法时使用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;     
     }       
   ...
}
4个回答

13

是的,这两种方法几乎具有相同的效果。重新抛出异常会解开异常的堆栈 - 这意味着在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        
   ...
}

2

是的,结果是一样的。

然而,如果读取时出现错误,两者都会导致未关闭的流。您应该使用using块或try ... finally来确保流已关闭:

using (TextReader tr2 = new StreamReader(nfilepath)) {
  resultN = tr2.ReadLine();
}

请注意,此代码中没有Closeusing块将处理StreamReader,它会关闭流。 using块被编译为try ... finally,用于确保StreamReader始终被处理,但异常会冒泡到调用方法。

2

首先,你应该使用带有资源的using块,因为这将正确关闭你的资源。第二个例子基本上是无用的,因为你在异常处理程序中没有做任何工作。你应该删除它,或者将其包装在另一个异常中以添加一些信息。


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}

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接