我对C#中如何引发异常感到非常困惑。如果发生异常,请在try块中, 1.它被扔到捕获块, 2.当且仅当catch块捕获到它时,才会执行finally块。 3.如果catch语句捕获了finally块,则最后执行该块。
但是,当我尝试运行下面的程序时,输出为A,B而不是BA。我的理解是否有问题?谢谢。
class Program
{
public static void Main(string[] args)
{
try
{
int a = 2;
int b = 10 / a;
try
{
if (a == 1)
a = a / a - a;
if (a == 2)
{
int[] c = { 1 };
c[8] = 9;
}
}
finally
{
Console.WriteLine("A");
}
}
catch (IndexOutOfRangeException e)
{
Console.WriteLine("B");
}
Console.ReadLine();
}
}
异常发生在a == 2中,我知道外部捕获将捕获此异常。但是,最后要先执行吗?有什么原因可以说明这一点?
从C#文档中我们知道,无论是否发生异常,都将执行finally块。
但是,我的finally块永远不会执行,因此我遇到了运行时错误
class Program
{
public static void Main(string[] args)
{
try
{
int a = 2;
int b = 10 / a;
try
{
if (a == 1)
a = a / a - a;
if (a == 2)
{
int[] c = { 1 };
c[8] = 9;
}
}
finally
{
Console.WriteLine("A");
}
}
finally{
Console.WriteLine("finally");
}
Console.ReadLine();
}
}
答案 0 :(得分:4)
finally
在控件出于任何原因离开其附着的try
块时执行。不仅是在同一级别上有一个catch
块-还是一个fault
处理程序(按CLR术语),我认为我们仍然无法在C#中做到这一点。
因此它进入打印finally
的{{1}},因为控制权离开了该A
块。由于外部try
块中捕获的异常而将其保留。但是,这不会改变任何时间/顺序。
请注意,如果代码中的任何地方都没有完全捕获到异常,则可能会出现一些奇怪的情况。异常处理分为两个阶段。在第一阶段,它将尝试为异常找到合适的catch
子句,其中可能包括执行保护子句(when
,C#6及更高版本)。在第二阶段中,它将展开堆栈并根据嵌套要求执行任何catch
子句,然后达到定义将处理异常的finally
子句的正确级别 1 。
我认为,在某些环境中,如果第一阶段根本找不到合适的异常处理程序(catch
子句) ,则整个托管环境可能会被拆除。在这种情况下,不会执行catch
子句。
所有符合CLR标准的必需。第12.4.2.5节规定:
发生异常时,CLI 在数组中搜索第一个受保护的块
- 的区域
保护一个包含当前指令指针和
是catch处理程序块和
谁的过滤器希望处理异常
如果在当前方法中找不到匹配项,则搜索调用方法,依此类推。 如果找不到匹配项 CLI将转储堆栈跟踪并中止程序。
(我的重点)
1 使用Flydog57's example的变体以及C#7局部函数来说明:
finally
此打印:
using System;
namespace PlayAreaCSCon
{
internal class Program
{
static void Main(string[] args)
{
TestTryCatchFinally();
Console.WriteLine("Complete");
Console.ReadLine();
}
private static void TestTryCatchFinally()
{
try
{
Console.WriteLine("Start Outer Try");
try
{
Console.WriteLine("Start Inner Try");
throw new Exception("Exception from inner try");
}
finally
{
Console.WriteLine("In Inner Finally");
}
}
catch (Exception ex) when (GuardHelper(ex))
{
Console.WriteLine("In outer catch");
}
finally
{
Console.WriteLine("In outer finally");
}
bool GuardHelper(Exception ex)
{
Console.WriteLine("In outer guard");
return true;
}
}
}
}
说明异常处理的两次通过特性(Start Outer Try
Start Inner Try
In outer guard
In Inner Finally
In outer catch
In outer finally
Complete
在之前 In outer guard
打印)
答案 1 :(得分:0)
如果您有一个try-catch-finally块,那么将catch放在最后是正确的。但是在这里,try-finally和try-catch块是按照从内到外的顺序运行的。因此,最终运行优先。
答案 2 :(得分:0)
它应该看起来像这样(具体取决于您实际要做什么)
localhost:8080/ShoppingSocieties/Shopping/products/purchase?id=1
答案 3 :(得分:0)
在您的第一个代码中,finally
(A)在catch
(B)之前运行的原因是,当引发异常时,您退出内部块(导致{{1 }}运行)在外部代码块的finally
开始发挥作用之前。考虑以下代码:
catch
如果运行此代码,则会得到以下输出:
private void TestTryCatchFinally()
{
try
{
Debug.WriteLine("Start Outer Try");
try
{
Debug.WriteLine("Start Inner Try");
throw new Exception("Exception from inner try");
Debug.WriteLine("End of Inner Try - never reaced");
}
//remove this catch block for second test
catch (Exception)
{
Debug.WriteLine("In inner catch");
}
//end of code to remove
finally
{
Debug.WriteLine("In Inner Finally");
}
}
catch (Exception)
{
Debug.WriteLine("In outer catch");
}
finally
{
Debug.WriteLine("In outer finally");
}
}
您期望的是什么。但是,如果删除内部catch块(如代码中所述),则会得到以下输出:
Start Outer Try
Start Inner Try
Exception thrown: 'System.Exception' in MyTestApp.exe
In inner catch
In Inner Finally
In outer finally
在这种情况下,一旦执行退出内部try块,最终代码就会执行。然后外面的挡块轮到了。
答案 4 :(得分:-1)
我可能缺少一些东西。您不需要以下内容吗?
try
{
}
catch (Exception ex)
{
}
finally
{
}
通过使用finally{}
块,可以确保某些语句将始终运行