让一个例外泡沫起来

时间:2011-07-06 09:03:29

标签: c# exception exception-handling

如何正确让异常冒泡?
如果我在调用方法时使用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 个答案:

答案 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();
}

请注意,此代码中没有Closeusing块会释放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}

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