try catch finally块是如何工作的?

57
C# 中,try catch finally 块如何工作?
如果发生异常,它将跳转到 catch 块,然后跳转到 finally 块。
但如果没有错误,catch 块不会运行,那么 finally 块会运行吗?

1
@MatíasFidemraizer:我非常支持实验,但这并不能告诉你语言的保证。有些你可能会通过实验“发现”的东西,是不可靠的。 - Jon Skeet
@JonSkeet 我是在一般情况下说的,不是针对你的建议(你的链接),但我的意思是检查C#中try/catch/finally如何工作是可以通过这段代码发现的:try { } catch{ } finally { Trace.WriteLine("我在这里!"); } 例如 :) - Matías Fidemraizer
@MatíasFidemraizer:但这正是我的观点——它展示了在这种特定情况下它的作用,但它并没有告诉你如果(比如说)你在try块内返回会发生什么。是的,实验很好——但我通常更愿意尽可能地相信规范。 - Jon Skeet
2
@JonSkeet 百分之百同意。我总是更喜欢阅读文档页面,了解某种语言或API功能的确切行为方式。但我的意思是,如果没有阅读所谓的文档或至少尝试自己编写示例代码,我不会在论坛或SO上提问。但再次强调,规范>试错。 - Matías Fidemraizer
当一个返回语句执行时,控制/程序流会返回到调用该方法或函数的脚本、函数或方法中。这意味着在调用的函数内部返回语句后面的任何内容都不会被执行。因此,如果你在一行上有一个返回语句,然后在下一行有一个异常,它不会执行异常。如果没有返回语句,异常将被触发,捕获将捕获它们,如果使用了finally块,则将执行其中的任何内容。退出、清理、返回,你想要什么就写什么,但实践中最好只进行必要的清理操作,不要做太多其他的事情。 - CodingInTheUK
如果你从“catch块”中抛出错误,它将不会在“finally块”中运行代码。 - Muflix
6个回答

56

是的,无论是否存在异常,finally块都会被执行。

尝试
    [ 尝试语句 ]
    [ 退出尝试 ]
[ 捕获 [ 异常 [ As 类型 ] ] [ When 表达式 ]
    [ catch语句 ]
    [ 退出尝试 ] ]
[ 捕获 ... ]
[ 最终
    [ finally语句 ] ] --始终运行
结束尝试

参见:http://msdn.microsoft.com/en-us/library/fk6t46tz%28v=vs.80%29.aspx


20
一个 FINALLY 块有什么意义?不管怎样,TRY 块外的下一行代码都会被执行,为什么还要加一个 FINALLY? - Doug
旧帖/评论。@Doug - 我的实例是记录任何API调用,无论是否出现错误。因此,使用finally,而不是在try块中使用(2)“log”调用,然后再使用catch。 - Rob Scott
8
如果在try/catch中的方法内部返回,那么try-catch语句块之外的代码将不会执行,但是finally语句块会执行。请看我在这里的附加回答。 - Mayer Spitz
2
@Doug - 如果在 CATCH 块内引发异常或者从该块中返回,TRY 块外的下一行代码将不会被执行,因此你可以使用 FINALLY 块来放置必须运行的代码。 - Joao Leme

13

如果没有异常发生,那么最终子句将被执行。以一个例子来说明。

     try
        {
            int a = 10;
            int b = 20;
            int z = a + b;
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        finally
        {
            Console.WriteLine("Executed");
        }

所以即使发生异常,finally语句块也会被执行。


但是这样做也可以: try{ int a = 10; int b = 20; int z = a + b; } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("已执行"); - Nabil Akhlaque

13
finally块将在方法返回之前始终执行。 尝试运行下面的代码,您会注意到finally语句中的Console.WriteLine("executed")RunTry()有机会返回之前就已经执行了。
static void Main(string[] args)
{
    Console.WriteLine("Hello World!");
    Console.WriteLine(RunTry());
    Console.ReadLine();
}
public static int RunTry()
{
    try
    {
        throw new Exception();
    }
    catch (Exception)
    {
        return 0;
    }
    finally
    {
        Console.WriteLine("executed");
    }
    Console.WriteLine("will not be executed since the method already returned");
}

查看结果:

Hello World!
executed
0

1
无论如何,finally块始终会执行。 只需尝试此方法。
     public int TryCatchFinally(int a, int b)
    {
        try
        {
            int sum = a + b;
            if (a > b)
            {
                throw new Exception();
            }
            else
            {
                int rightreturn = 2;
                return rightreturn;
            }
        }
        catch (Exception)
        {
            int ret = 1;
            return ret;
        }
        finally
        {
            int fin = 5;
        }
    }

1

是的,finally块总是会被执行。

即使try后面没有catch块,finally块仍然会被执行

基本上,finally可以用于释放资源,例如文件流、数据库连接和图形处理程序,而不必等待运行时中的垃圾收集器来完成对象的最终处理。

       try
        {
            int a = 10;
            int b = 0;
            int x = a / b;
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
        finally
        {
            Console.WriteLine("Finally block is executed");
        }
        Console.WriteLine("Some more code here");

输出:

System.DivideByZeroException:尝试除以零。

最终块被执行

其余代码

来源:C#中的异常处理(包括try-catch-finally块详细信息)


0
        try
        {
            //Function to Perform
        }
        catch (Exception e)
        {
         //You can display what error occured in Try block, with exact technical spec (DivideByZeroException)
            throw; 
            // Displaying error through signal to Machine, 
            //throw is usefull , if you calling a method with try from derived class.. So the method will directly get the signal                
        }

        finally  //Optional
        {
            //Here You can write any code to be executed after error occured in Try block
            Console.WriteLine("Completed");
        }

2
无论 catch 是否捕获到错误,finally 始终会被执行。 - Mason

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接