我见过这个例子:
static void Main(string[] args)
{
Console.WriteLine("Start");
try
{
SomeOperation();
}
catch (Exception) when (EvaluatesTo())
{
Console.WriteLine("Catch");
}
finally
{
Console.WriteLine("Outer Finally");
}
}
private static bool EvaluatesTo()
{
Console.WriteLine($"EvaluatesTo: {Flag}");
return true;
}
private static void SomeOperation()
{
try
{
Flag = true;
throw new Exception("Boom");
}
finally
{
Flag = false;
Console.WriteLine("Inner Finally");
}
}
Run Code Online (Sandbox Code Playgroud)
这会产生下一个输出:
Start
EvaluatesTo: True
Inner Finally
Catch
Outer Finally
Run Code Online (Sandbox Code Playgroud)
这对我来说听起来很奇怪,而且我正在寻找一个很好的解释这个命令,将它包含在我脑海中.我以前期待finally块执行when:
Start
Inner Finally
EvaluatesTo: True
Catch
Outer Finally
Run Code Online (Sandbox Code Playgroud)
文档说明这个执行顺序是正确的,但它没有详细说明为什么这样做,以及这里执行顺序的确切规则是什么.
Lua*_*aan 38
您可能已经被告知,当发生异常处理时,每个方法都是单独考虑的.也就是说,由于你的内部方法有一个try...finally,任何异常都会先触发finally,然后它会"查找" try更高的值.事实并非如此.
根据ECR的CLR规范(ECMA-335,I.12.4.2.5异常处理概述):
发生异常时,CLI将在阵列中搜索第一个受保护的块
- 保护包含当前指令指针和区域的区域
- 是一个catch处理程序块和
- 谁的过滤器希望处理异常
如果在当前方法中找不到匹配项,则搜索调用方法,依此类推.如果未找到匹配项,CLI将转储堆栈跟踪并中止该程序.
如果找到匹配项,CLI会将堆栈移回到刚定位的点,但这次调用finally和fault处理程序.然后它启动相应的异常处理程序.
如您所见,该行为100%符合规范.
try中SomeOperationtryinMainfinally 在 SomeOperation当然,finallyin Main不是它的一部分 - 它将在执行离开受保护块时执行,而不管异常.
编辑:
只是为了完整 - 这一直是这样的.唯一改变的是C#现在支持异常过滤器,它允许您观察执行的顺序.VB.NET支持版本1的异常过滤器.
| 归档时间: |
|
| 查看次数: |
1267 次 |
| 最近记录: |