C#中的异常处理-最终尝试捕获

时间:2018-07-30 17:56:21

标签: c# asp.net .net asp.net-mvc exception-handling

对于finally块,我有些困惑。我知道无论是否有异常,都可以执行finally块。

我有2种情况:-

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代码块不执行。

2 个答案:

答案 0 :(得分:2)

实际上,try-catch-finally块的作用如下:

尝试

放置潜在问题代码的地方。如果生成异常,则会引发异常。

赶上

catch是唯一会被捕获 的异常的块。由此得名。因此,当引发异常时,如果要确保不使程序“挂起”,则必须catch进行异常。

最后

进行清理。举例来说,如果您的try块中有某个数组,并且想在发生异常的情况下清理它,那么这里就是这样做的地方。

最后尝试

documentation说:

  

在已处理的异常内,可以保证关联的finally块可以运行。 但是,如果未处理异常,则finally块的执行取决于异常展开操作的触发方式。而这又取决于计算机的设置方式。

意思是,如果您没有捕获到异常,则取决于情况是否运行finally

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

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

您正在尝试除以零,这会产生异常。但是没有被“捕获”的地方,因此程序挂起:

enter image description here

因此,如果您在此处添加一个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内还有第二个非法分区,并且没有抛出异常的陷阱,因此程序挂起。

因此,如果您将其修改为在第一个try-catch中有第二个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,除非您可以证明为什么不想要一个。

答案 1 :(得分:0)

遵循article MSDN

  

在已处理的异常内,可以保证关联的finally块   要运行

这意味着对于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
  

如果未处理异常,则执行finally块   取决于如何触发异常展开操作。在   取决于您计算机的设置方式。

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

在您的情况2中,DivideByZeroException中的catch或情况1中的try中有一个例外finally,将被执行。 / p>

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