如果finally块抛出异常,到底会发生什么?
具体来说,如果在finally块中途抛出异常会发生什么。这个块中的其余语句(之后)是否被调用?
我知道异常会向上传播。
如果finally块抛出异常,到底会发生什么?
具体来说,如果在finally块中途抛出异常会发生什么。这个块中的其余语句(之后)是否被调用?
我知道异常会向上传播。
当前回答
它抛出一个异常;)您可以在其他catch子句中捕获该异常。
其他回答
我必须这样做是为了捕捉一个错误,试图关闭一个从未因为异常而打开的流。
errorMessage = string.Empty;
try
{
byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(xmlFileContent);
webRequest = WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.ContentType = "text/xml;charset=utf-8";
webRequest.ContentLength = requestBytes.Length;
//send the request
using (var sw = webRequest.GetRequestStream())
{
sw.Write(requestBytes, 0, requestBytes.Length);
}
//get the response
webResponse = webRequest.GetResponse();
using (var sr = new StreamReader(webResponse.GetResponseStream()))
{
returnVal = sr.ReadToEnd();
sr.Close();
}
}
catch (Exception ex)
{
errorMessage = ex.ToString();
}
finally
{
try
{
if (webRequest.GetRequestStream() != null)
webRequest.GetRequestStream().Close();
if (webResponse.GetResponseStream() != null)
webResponse.GetResponseStream().Close();
}
catch (Exception exw)
{
errorMessage = exw.ToString();
}
}
如果创建了webRequest,但在执行过程中发生连接错误
using (var sw = webRequest.GetRequestStream())
然后finally将捕获一个异常,试图关闭它认为是打开的连接,因为webRequest已经创建。
如果finally在内部没有try-catch,这段代码在清理webRequest时会导致一个未处理的异常
if (webRequest.GetRequestStream() != null)
从那里,代码将退出,而没有正确处理所发生的错误,因此会导致调用方法出现问题。
希望这能起到示范作用
如果有一个异常挂起(当try块有finally但没有catch时),新异常将替换该异常。
如果没有异常挂起,它就像在finally块外抛出异常一样工作。
传播异常。
对于这样的问题,我通常在Visual Studio中打开一个空的控制台应用程序项目,并编写一个小示例程序:
using System;
class Program
{
static void Main(string[] args)
{
try
{
try
{
throw new Exception("exception thrown from try block");
}
catch (Exception ex)
{
Console.WriteLine("Inner catch block handling {0}.", ex.Message);
throw;
}
finally
{
Console.WriteLine("Inner finally block");
throw new Exception("exception thrown from finally block");
Console.WriteLine("This line is never reached");
}
}
catch (Exception ex)
{
Console.WriteLine("Outer catch block handling {0}.", ex.Message);
}
finally
{
Console.WriteLine("Outer finally block");
}
}
}
当您运行程序时,您将看到执行catch和finally块的确切顺序。请注意,在抛出异常后,finally块中的代码将不会被执行(事实上,在这个示例程序中,Visual Studio甚至会警告你,它已经检测到不可访问的代码):
Inner catch block handling exception thrown from try block. Inner finally block Outer catch block handling exception thrown from finally block. Outer finally block
额外的评论
正如Michael Damatov指出的,try块中的异常如果不在(内部)catch块中处理,就会被“吃掉”。事实上,在上面的例子中,重新抛出的异常并没有出现在外层catch块中。为了更清楚地说明这一点,请看下面稍作修改的示例:
using System;
class Program
{
static void Main(string[] args)
{
try
{
try
{
throw new Exception("exception thrown from try block");
}
finally
{
Console.WriteLine("Inner finally block");
throw new Exception("exception thrown from finally block");
Console.WriteLine("This line is never reached");
}
}
catch (Exception ex)
{
Console.WriteLine("Outer catch block handling {0}.", ex.Message);
}
finally
{
Console.WriteLine("Outer finally block");
}
}
}
正如你可以从输出中看到的,内部异常被“丢失”(即被忽略):
Inner finally block Outer catch block handling exception thrown from finally block. Outer finally block
快速(相当明显的)代码片段保存“原始异常”(在try块中抛出)并牺牲“finally异常”(在finally块中抛出),以防原始异常对你更重要:
try
{
throw new Exception("Original Exception");
}
finally
{
try
{
throw new Exception("Finally Exception");
}
catch
{ }
}
当执行上面的代码时,“原始异常”向上传播调用堆栈,“最终异常”丢失。