C# 中的异常处理 - try catch finally

Exception Handling in c# - try catch finally

我对 finally 块有点困惑。我知道不管是否有异常,finally 块都会被执行。

我有两种情况:-

1)如果try块出现异常,我没有为这个try块写任何catch块,但是我有一个finally块,那么finally块会被执行吗?如果异常未处理,是否执行 finally 块?

下面是一个示例代码:-

static void Main(string[] args)
            {
                int x = 0;
                try
                {
                    int divide = 12 / x;
                }
                //catch (Exception ex)
                //{
                //    int divide = 12 / x;
                //    Console.WriteLine(ex.Message);

                //}
                finally
                {
                    Console.WriteLine("I am finally block");
                }
                Console.ReadLine();
            }

2) 如果catch块出现异常,finally块会被执行吗? 下面是示例代码:-

static void Main(string[] args)
    {
        int x = 0;
        try
        {
            int divide = 12 / x;
        }
        catch (Exception ex)
        {
            int divide = 12 / x;   // this will throw exception in catch block
            Console.WriteLine(ex.Message);

        }
        finally
        {
            Console.WriteLine("I am finally block");
        }
        Console.ReadLine();
    }

我已经尝试了这些代码,但没有看到 finally 块被执行。 请解释为什么没有执行 finally 块。

用非常简单的术语来说,这些是 try-catch-finally 块的作用:

尝试

放置可能有问题的代码的地方。如果产生异常,则抛出异常。

抓住

Catch 是唯一一个可以捕获 异常的块。由此得名。所以当抛出异常时,如果你想确保程序不'hang',你必须catch抛出异常。

终于

做你的清理工作。比方说,如果你的 try 块中有一些数组,并且你想在出现异常时清理它,那么这里就是这样做的地方。

最后尝试

documentation 说:

Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.

的意思是,如果你没有捕捉到你的异常,这取决于finally是否是运行的情况。

考虑到这一点,让我们看看您的第一个代码块。

static void Main(string[] args)
{
    int x = 0;
    try
    {
        int divide = 12 / x;
    }
    finally
    {
        Console.WriteLine("I am finally block");
    }
    Console.ReadLine();
}

您正在尝试除以零,这会生成异常。但是没地方放'caught',所以程序挂了:

因此,如果您在此处添加一个 catch 块,现在它将允许顺利航行并前往您的 finally

try
{
    int divide = 12 / x;
}
catch (Exception ex)
{
    Console.WriteLine("Oops. Division by Zero.");
}
finally
{
    Console.WriteLine("I am finally block");
}

现在我们来看第二个代码片段。我将做一个小修改,翻转 catch.

中两行代码的顺序
static void Main(string[] args)
{
    int x = 0;
    try
    {
        int divide = 12 / x;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        int divide = 12 / x;
    }
    finally
    {
        Console.WriteLine("I am finally block");
    }
    Console.ReadLine();
}

现在,catch 块捕获第一个非法除法抛出的异常并打印一条消息。但是 catch 中还有第二个非法除法,并且没有捕获到抛出的异常,因此程序挂起。

因此,如果您将其修改为在第一个 catch 中添加第二个 try-catch,如下所示:

static void Main(string[] args)
{
    int x = 0;
    try
    {
        int divide = 12 / x;
    }
    catch (Exception ex)
    {
        try
        {
            Console.WriteLine(ex.Message);
            int divide = 12 / x;
        }
        catch (Exception ex2)
        {
            Console.WriteLine(ex2.Message);
        }
    }
    finally
    {
        Console.WriteLine("I am finally block");
    }
    Console.ReadLine();
}

现在它会捕捉到两个异常,你就可以开始了。

所以我的想法是,如果你有一个 try,你应该尝试有一个 catch,除非你能证明你为什么不想要一个。

遵循 article MSDN

Within a handled exception, the associated finally block is guaranteed to be run

这意味着对于try catch finally,必须执行finally中的代码。

        int x = 0;
        try
        {
            int divide = 12 / x;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            Console.WriteLine("I am finally block");
        }
        Console.ReadLine();

输出:

Attempted to divide by zero. // catch Console.WriteLine(ex.Message);
I am finally block // finally

If the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.

这意味着这取决于抛出的异常 finally 代码是否会被执行。如果 WhosebugException 或异常,即 ExecutionEngineException,可能会调用 Environment.FailFast() 或 Environment.Exit(),您的 finally 代码将不会被执行,因为您的应用程序之前已关闭。

你的case 2,在case 1的catch或者try中出现异常DivideByZeroException,会执行本例中的代码finally .

int x = 0;
try
{
    int divide = 12 / x;
}
catch (Exception ex)
{
    int divide = 12 / x;   // no handled
    Console.WriteLine(ex.Message);

}
finally
{
    Console.WriteLine("I am finally block");
}
Console.ReadLine();

输出:

I am finally block // finally
Run-time exception (line 16): Attempted to divide by zero. // exception non handled catch by the level plus high that cause crashing the application