如果finally块抛出异常,到底会发生什么?

具体来说,如果在finally块中途抛出异常会发生什么。这个块中的其余语句(之后)是否被调用?

我知道异常会向上传播。


当前回答

异常向上传播,应该在更高的级别进行处理。如果不在更高的级别处理异常,应用程序将崩溃。“finally”块执行在抛出异常的地方停止。

无论是否存在异常,“finally”块都保证执行。

如果“finally”块在try块中发生异常后被执行, 如果这个异常没有被处理 如果finally块抛出异常

然后,try块中发生的原始异常将丢失。

public class Exception
{
    public static void Main()
    {
        try
        {
            SomeMethod();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    public static void SomeMethod()
    {
        try
        {
            // This exception will be lost
            throw new Exception("Exception in try block");
        }
        finally
        {
            throw new Exception("Exception in finally block");
        }
    }
} 

关于细节的好文章

其他回答

在另一个异常活动时抛出异常将导致第一个异常被第二个(稍后)异常所取代。

下面是一些代码,说明发生了什么:

    public static void Main(string[] args)
    {
        try
        {
            try
            {
                throw new Exception("first exception");
            }
            finally
            {
                //try
                {
                    throw new Exception("second exception");
                }
                //catch (Exception)
                {
                    //throw;
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

运行代码,您将看到“第二个异常” 取消try和catch语句的注释,您将看到“第一个异常” 也取消注释抛出;语句,您将再次看到“第二个异常”。

如果finally块抛出异常,到底会发生什么?

该异常向外和向上传播,并且将(可以)在更高的级别进行处理。

finally块在抛出异常之后将不会完成。

如果finally块是在处理之前的异常期间执行的,那么第一个异常将丢失。

c# 4语言规范§8.9.5:如果finally块抛出另一个异常,则当前异常的处理将终止。

我必须这样做是为了捕捉一个错误,试图关闭一个从未因为异常而打开的流。

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) 

从那里,代码将退出,而没有正确处理所发生的错误,因此会导致调用方法出现问题。

希望这能起到示范作用

它抛出一个异常;)您可以在其他catch子句中捕获该异常。

如果有一个异常挂起(当try块有finally但没有catch时),新异常将替换该异常。

如果没有异常挂起,它就像在finally块外抛出异常一样工作。