问题提出
1 try 2 { 3 return x; 4 } 5 finally 6 { 7 x = null; 8 }
上面这段代码到底怎么执行的?
try..catch..finally 介绍
在MSDN中,try..catch..finally 的介绍如下:
- finally 块用于清除 try 块中分配的任何资源,以及运行任何即使在发生异常时也必须执行的代码。 控制总是传递给 finally 块,与 try 块的退出方式无关。
- catch 用于处理语句块中出现的异常,而 finally 用于保证代码语句块的执行,与前面的 try 块的退出方式无关。
- catch 和 finally 一起使用的常见方式是:在 try 块中获取并使用资源,在 catch 块中处理异常情况,并在 finally 块中释放资源。
典型用法:
1 void ReadFile(int index) 2 { 3 string path = @"c:\users\public\test.txt"; 4 char[] buffer = new char[10]; 5 6 StreamReader file = new StreamReader(path); 7 try 8 { 9 file.ReadBlock(buffer, index, buffer.Length); 10 } 11 catch (IOException e) 12 { 13 Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message); 14 } 15 finally 16 { 17 if (file != null) 18 { 19 file.Close(); 20 } 21 } 22 }
通常 finally 中的代码只负责清理资源。
那么,如果 finally 中包含业务逻辑,try..finally..的执行顺序会对业务逻辑有怎样的影响呢?
try..finally 的执行顺序
回到问题,
void Main() { Console.WriteLine(TestTryFinally()); } public string TestTryFinally() { string x = "init"; try { x = "try"; return x; } finally { x = "finally"; } }
这里的执行顺序是:
- 执行 return 之前的代码
- 对 return 语句求值
- 执行 finally 中的代码
- 在第 2 步中的求值结果被返回
所以,具体是否对返回值有影响,得看 x 变量的类型。如果是不可变类型,则 finally 中的代码对 return 的求值结果没有任何影响。而如果是可变类型,则 finally 中的代码会改变 return 求值结果的内容。
上述代码,在 x 类型为 string 时,返回值为 "try"。
查看 IL 代码,
1 IL_0000: ldarg.0 2 IL_0001: call UserQuery.TestTryFinally 3 IL_0006: call System.Console.WriteLine 4 5 TestTryFinally: 6 IL_0000: ldstr "init" 7 IL_0005: stloc.0 // x 8 IL_0006: ldstr "try" 9 IL_000B: stloc.0 // x 10 IL_000C: ldloc.0 // x 11 IL_000D: stloc.1 // CS$1$0000 12 IL_000E: leave.s IL_0017 13 IL_0010: ldstr "finally" 14 IL_0015: stloc.0 // x 15 IL_0016: endfinally 16 IL_0017: ldloc.1 // CS$1$0000 17 IL_0018: ret
发现在 stloc.1 处会创建 CS 0000 临时变量来存储 return 返回值。
从程序集反编译代码查看结果,程序已经被优化。
1 // ConsoleApplication11_TryFinallyTest.Program 2 public string TestTryFinally() 3 { 4 string result; 5 try 6 { 7 string x = "try"; 8 result = x; 9 } 10 finally 11 { 12 } 13 return result; 14 }
更多测试结果

参考资料
- try-catch-finally(C# 参考)
- What really happens in a try { return x; } finally { x = null; } statement?
本文转自匠心十年博客园博客,原文链接:http://www.cnblogs.com/gaochundong/p/try_finally_statement.html,如需转载请自行联系原作者