try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
在上面的块中,finally块是什么时候调用的?在投掷e之前或最终被调用然后赶上?
答案 0 :(得分:115)
在重新抛出e之后(即在执行catch块之后)将调用它
7年之后编辑这个 - 一个重要的注意事项是,如果e
没有被调试堆栈进一步向上调用或由全局异常处理程序处理,那么finally
块可能永远不会执行。
答案 1 :(得分:74)
为什么不尝试一下:
outer try
inner try
inner catch
inner finally
outer catch
outer finally
带代码的(格式化为垂直空间):
static void Main() {
try {
Console.WriteLine("outer try");
DoIt();
} catch {
Console.WriteLine("outer catch");
// swallow
} finally {
Console.WriteLine("outer finally");
}
}
static void DoIt() {
try {
Console.WriteLine("inner try");
int i = 0;
Console.WriteLine(12 / i); // oops
} catch (Exception e) {
Console.WriteLine("inner catch");
throw e; // or "throw", or "throw anything"
} finally {
Console.WriteLine("inner finally");
}
}
答案 2 :(得分:30)
在阅读完这里的所有答案之后,看起来最终的答案是取决于:
如果在catch块中重新抛出异常,并且该异常被捕获到另一个catch块内,则所有内容都会根据文档执行。
但是,如果重新处理的异常未处理,则finally永远不会执行。
我在VS2010 w / C#4.0
中测试了此代码示例static void Main()
{
Console.WriteLine("Example 1: re-throw inside of another try block:");
try
{
Console.WriteLine("--outer try");
try
{
Console.WriteLine("----inner try");
throw new Exception();
}
catch
{
Console.WriteLine("----inner catch");
throw;
}
finally
{
Console.WriteLine("----inner finally");
}
}
catch
{
Console.WriteLine("--outer catch");
// swallow
}
finally
{
Console.WriteLine("--outer finally");
}
Console.WriteLine("Huzzah!");
Console.WriteLine();
Console.WriteLine("Example 2: re-throw outside of another try block:");
try
{
Console.WriteLine("--try");
throw new Exception();
}
catch
{
Console.WriteLine("--catch");
throw;
}
finally
{
Console.WriteLine("--finally");
}
Console.ReadLine();
}
这是输出:
示例1:重新抛出另一个try块:
- 外观尝试
----内心尝试 ----内部抓住 ----最终内心 - 外部捕获
- 最后结局 好哇!示例2:在另一个try块之外重新抛出:
--try
--catch未处理的异常:System.Exception:类型的异常' System.Exception'扔了。
在C:\ local source \ ConsoleApplication1 \ Program.cs中的ConsoleApplication1.Program.Main():第53行
答案 3 :(得分:23)
您的示例与此代码的行为相同:
try {
try {
// Do stuff
} catch(Exception e) {
throw e;
}
} finally {
// Clean up
}
作为旁注,如果你的意思是throw e;
(也就是说,抛出你刚刚抓到的同一个异常),那么只需{em> 就可以做throw;
,因为这将保留原始堆栈跟踪而不是创建新的跟踪。
答案 4 :(得分:12)
如果catch处理程序块中存在未处理的异常,则finally块将被完全零次调用
static void Main(string[] args)
{
try
{
Console.WriteLine("in the try");
int d = 0;
int k = 0 / d;
}
catch (Exception e)
{
Console.WriteLine("in the catch");
throw;
}
finally
{
Console.WriteLine("In the finally");
}
}
输出:
C:\用户\管理员\文件\ TestExceptionNesting \ BIN \推出> TestExceptionNesting.exe
尝试中的
在捕获
未处理的异常:System.DivideByZeroException:试图划分 零。在TestExceptionNesting.Program.Main(String [] args)中 C:\ users \ administrator \ documents \ TestExceptionNesting \ TestExceptionNesting.cs:第22行
C:\用户\管理员\文件\ TestExceptionNesting \ BIN \释放>
我今天在接受采访时被问到这个问题,面试官一直回过头来“你确定最终没有被召唤吗?”我不确定这是否意味着一个技巧问题,或者面试官是否有其他想法,并为我编写了错误的代码进行调试,所以我回家试了一下(构建并运行,没有调试器交互),只是为了让我的想法其余部分。
答案 5 :(得分:3)
一种简单的方法是调试代码并注意最终被调用。
答案 6 :(得分:1)
使用C#控制台应用程序进行测试,抛出异常后执行了最终代码:“应用程序错误对话框”已存在,在您选择“关闭程序”选项后,最终块在该控制台窗口中执行。 但是在最终代码块中设置断点,我永远不会打它。调试器一直停在throw语句处。 这是我的测试代码:
class Program
{
static void Main(string[] args)
{
string msg;
Console.WriteLine(string.Format("GetRandomNuber returned: {0}{1}", GetRandomNumber(out msg), msg) == "" ? "" : "An error has occurred: " + msg);
}
static int GetRandomNumber(out string errorMessage)
{
int result = 0;
try
{
errorMessage = "";
int test = 0;
result = 3/test;
return result;
}
catch (Exception ex)
{
errorMessage = ex.Message;
throw ex;
}
finally
{
Console.WriteLine("finally block!");
}
}
}
在VS2010中进行调试 - .NET Framework 4.0