1. 认识finally块
清理和释放资源
想象一下:你在化学实验室里做实验,等一切结束(哪怕你炸了几个烧瓶),你还是得收拾实验台、冲洗化学品、关灯。finally块就是干这个用的——它总会在try和catch之后执行,不管有没有异常发生。
try
{
// 这里写“危险”代码,可能会抛出异常
}
catch
{
// 这里捕获并处理异常
}
finally
{
// 这段代码总会执行,不管有没有异常
}
为什么要这样? 首先是为了保证资源一定被释放:比如关闭文件、断开数据库连接、解锁机房的门……如果没有finally,一旦出错,有些资源可能就“卡住”了——这就很麻烦。比如文件被锁住,连管理员都打不开。
为啥不能都写在catch里?
我们能不能直接在catch里释放资源?理论上可以。但如果一切顺利,catch根本不会执行。如果你想确保资源总是被释放,就得用finally。
现实开发中经常遇到这种情况:不管成功还是失败——都得收拾残局。这就是finally存在的意义。
2. finally块的特点
什么时候finally不会执行?
这是个小陷阱!finally几乎总是会执行。就算在try里有return(提前返回方法),或者抛出新异常,finally还是会被执行。
static void Test()
{
try
{
Console.WriteLine("到return之前");
return;
}
finally
{
Console.WriteLine("finally还是会执行!");
}
}
//调用Test()
Test();
输出:
// 到return之前
// finally还是会执行!
不过,如果你的程序突然“崩溃”了(比如电脑断电、进程被杀掉或者CLR挂了),finally就不会执行了。这种情况也没办法。
finally操作符和调用栈
调用栈我们下节课会详细讲,这里简单说下:它就像一摞被调用的方法,程序会“往下走”,直到找到合适的catch。
还有个重点:如果try里抛出异常,而catch没接住(比如没有合适的处理器),程序就会离开当前方法,继续沿着调用栈往上找,直到遇到合适的catch。但在这之前,每一层都会先执行finally块。
3. throw操作符:怎么自己抛异常
throw是啥,有啥用
有时候光捕获异常还不够——你可能需要自己造一个错误“扔”出去。这就得用throw操作符。
throw new Exception("这是我的专属错误!");
throw就是在跟CLR说:“我发现了大问题,扔个Exception出去,后面谁调用这段代码谁负责处理。”
throw不创建新异常的用法
你可以在catch块里用throw;,把刚刚捕获的异常再抛出去——比如你只处理了一部分错误,剩下的想让上层代码继续处理。
try
{
DangerousOperation();
}
catch (Exception ex)
{
LogError(ex);
throw; // 再次抛出当前异常,调用栈信息会保留
}
如果你写成throw ex;,调用栈信息就丢了——这是个坏习惯。
4. finally和throw一起用会怎样?
抛异常时finally也会执行
来看看:如果在try里throw了异常,同时又有finally,会发生什么?
try
{
Console.WriteLine("抛异常前...");
throw new Exception("try块里的错误!");
}
catch
{
Console.WriteLine("Catch捕获了错误。");
}
finally
{
Console.WriteLine("Finally执行了。");
}
结果如下:
抛异常前...
Catch捕获了错误。
Finally执行了。
如果没有合适的catch,finally还是会在程序崩溃前执行。
细节:如果finally里也throw会怎样?
如果在finally里也抛出throw,那这个异常会覆盖之前的异常。也就是说,try/catch里的异常信息就丢了。所以一般不建议在finally里再抛异常,尤其是前面已经有异常的时候。
try
{
throw new Exception("try里的错误");
}
finally
{
throw new Exception("finally里的错误");
}
// 结果:外面只会看到"finally里的错误"
5. 实用建议和常见错误
新手最容易忘的点
- 释放资源时没用finally块,只靠catch。
- 把可能抛新异常的代码写进finally——这样容易出意外。
- 忘了return在try里不会“跳过”finally——它总会执行。
finally的替代方案:怎么选?
有了using结构(我们后面会详细讲),释放资源更方便了,但其实using底层还是用的finally。遇到特殊情况(比如解锁、发错误通知),还是得用finally。
面试官为啥喜欢考finally
每个写过高并发服务器的面试官都爱问finally。常见问题:“如果try里有return,finally里有throw会怎样?”或者“异常时资源一定能释放吗?”现在你不仅能答出来,还能讲明白原理。你能说清楚finally怎么用、为啥用、啥时候用——没有它,靠谱的代码根本写不出来。
GO TO FULL VERSION