前两天做项目,在使用MySqlDataReader时遇到了问题,后来发现是遇到异常时没有关闭myReader导致的。要解决那个问题就要明白try—catch—finally的用法了。
1. 为什么要用finally??因为异常进入catch后有时需要直接返回,不继续执行后面的语句,但是还有一部分工作要做(比如释放资源之类的)这时就要写到finally里面。
2. 说明:
try { //可能发生异常的代码。一旦发现异常,则立即跳到catch执行。否则不会执行catch里面的内容 } catch { //除非try里面执行代码发生了异常,否则这里的代码不会执行 //因为异常了,有时直接在这里就return了 } finally { //不管什么情况都会执行,包括try或 catch 里面用了return ,可以理解为只要执行了try或者catch,就一定会执行 finally }
3. 用途举例:我们可以在try块中尝试打开数据库,然后读取数据,然后直接把得到的数据return出去,关闭数据连接的工作就交给finally来做——finally中先判断数据库是否正常打开了,打开了就关闭。这样代码写起来很清晰,每个部分各做各的事。这样我们也可以非常肯定的说,无论发生什么情况(只要不是进程被强行杀掉),finally中的内容一定是要执行的。
4. finally块中是不允许写return的,如果一定要写,就会得到一个编译期错误,error CS0157:Control cannot leave the body of a finally clause
5. 先return?先finally?
既然finally一定是要执行的,即使try块中有return,那么这两者的执行顺便是怎么样的呢?简单做个实验
using System; public class TestClass1 ...{ public static void Main() ...{ Console.WriteLine("{0}", Func1()); } public static int Func1() ...{ int a = 1; try ...{ return a; } finally ...{ a++; } } }
结果为“1”。那么看上去是执行return在先,而finally在后了。真的是这样吗?
例子中我要return的a是一个值类型,那么如果是引用类型,结果又会如何呢?
using System; public class TestClass2 ...{ public int value = 1; } public class TestClass1 ...{ public static void Main() ...{ Console.WriteLine("{0}", Func2().value); } public static TestClass2 Func2() ...{ TestClass2 t = new TestClass2(); try ...{ return t; } finally ...{ t.value++; } } }这一次运行的结果是 2 。显然,运行 Func2() 返回的结果并不直接是 return 后面写的 t ,而是经过 finally 块执行后值发生变化的 t 。如何来解释这种区别呢?