C# 抛出异常时,为什么finally块不能执行?
很长一段时间以来,我认为它允许我释放C# 抛出异常时,为什么finally块不能执行?,c#,exception,try-catch,finally,try-finally,C#,Exception,Try Catch,Finally,Try Finally,很长一段时间以来,我认为它允许我释放finally块中的所有资源,并且我认为如果try块中发生异常,那么finally块中的资源仍将被释放。但情况似乎并非如此 我有以下代码: using System; public sealed class Program { public static void Main() { try { int zero = 0; int i = 1/zero; } fi
finally
块中的所有资源,并且我认为如果try
块中发生异常,那么finally
块中的资源仍将被释放。但情况似乎并非如此
我有以下代码:
using System;
public sealed class Program
{
public static void Main()
{
try {
int zero = 0;
int i = 1/zero;
} finally {
Console.WriteLine("divide by zero"); //the line is never called
}
}
}
我从未到达打印到控制台的线路。这意味着我将无法释放finally
块中的资源,在这种情况下,在try
块中抛出异常
因此,我相信有两件事:要么我遗漏了什么,要么尝试
+最后
组合在C#中没有用例。第二条语句很有意义,因为我将使用下面的代码获得与上述代码相同的功能:
using System;
public sealed class Program
{
public static void Main()
{
int zero = 0;
int i = 1/zero;
Console.WriteLine("divide by zero"); //the line is never called
}
}
但我担心我可能会错过一些东西。那么,有人能确认这个组合是无用的,或者证明它不是无用的吗
更新
在能够调用小提琴中的finally
块的注释之后,我再次检查了VS代码,仍然没有看到任何输出
你的假设不正确(有时) 通过使用finally块,您可以清理所有被删除的资源 在try块中分配,即使出现异常,也可以运行代码 在try块中发生。通常,finally块的语句 当控件留下try语句时运行。控制权的转移可以 由于正常执行、中断执行而发生, continue、goto或return语句,或异常的传播 在try语句之外 但在某些情况下,它无法运行 在已处理的异常中,保证关联的finally块 待运行但是,如果异常未处理,则 最后,块取决于异常展开操作的方式 已触发。这又取决于计算机的设置方式 这里是重要的部分 通常,当未处理的异常结束应用程序时,无论 最后一个块是否运行并不重要但是,如果您有 finally块中即使在这种情况下也必须运行的语句, 一种解决方案是向try finally语句添加catch块。 或者,您可以捕获可能在 try-finally语句的try块位于调用堆栈的较高位置。
try/catch/finally
与释放资源无关。这是严格意义上的应用程序流程和错误处理构造。您生活在托管代码中,垃圾收集器释放资源。此构造执行以下操作
try
{
int zero = 0;
int i = 1/zero;
}
catch (DividedByZeroException ex)
{
Console.WriteLine(Exception handled);
throw; // propagate ex to caller
}
finally
{
Console.WriteLine("Method ended execution"); // called with or without exception
}
我相信这是因为您必须在未处理的错误上中断VS,从而在显示异常时中断VS步骤。如果您编译它并在命令行上手动运行它,我相信您将看到“除以零”。此外,您可以“处理”错误,然后查看预期的行为,而不是更改VS设置 例如:
using System;
public sealed class Program
{
public static void Main()
{
try
{
int zero = 0;
int i = 1 / zero;
}
catch
{
}
finally
{
Console.WriteLine("divide by zero");
}
}
}
我想分享以下摘自C#via CLR一书的摘录,这本书向我阐明了为什么最终块可能不会被调用 如果在try块内执行的代码(或从try块内调用的任何方法)引发异常,CLR将开始搜索catch类型与或相同的catch块 引发的异常的基类型。如果没有任何捕获类型与异常匹配,CLR将继续 在调用堆栈中搜索与异常匹配的捕获类型。如果到达 在调用堆栈的顶部,找不到具有匹配catch类型(未处理的异常)的catch块 发生 一旦CLR找到一个具有匹配catch类型的catch块,它就会在所有内部执行代码 最后是块,从代码引发异常的try块内开始并停止 使用与异常匹配的catch块。请注意,与 与异常匹配的catch块尚未执行。此finally块中的代码不会 执行,直到处理catch块中的代码执行完毕 内部finally块中的所有代码执行后,handling catch块中的代码 执行
因此,这意味着在任何未处理的异常情况下,finally块将不会被调用。@MichaelRandall尝试使用.NET核心编译器:@JohnathanBarclay,oh。你是我的救星。这是由于.NET核心的转换,而我已经习惯了.NET框架。非常感谢。@JohnathanBarclay,我相信你的评论就是我想要的答案。请你把它作为一个答案加上好吗?这能回答你的问题吗@迈克尔·兰德尔的回答解释了实际原因。我的小提琴只是一种观察。是的。我看到添加了
catch
块的输出。谢谢。哇。。我不知道上一句话中的警告。似乎有点违反直觉。。。但是,再一次,我认为我从来没有真正需要阅读try/catch文档(或者我是这么认为的!)。@BrootsWaymb这些讨厌的文档中隐藏着令人惊讶的东西:)@MichaelRandall,这是否意味着最后的文档引用是由.NET核心支持的,而不是由.NET框架支持的?@qqq简而言之,使用catch finally
来处理异常,以确保运行某个程序。不要依赖于环境environment@MichaelRandall,明白了。非常感谢。请您也告诉我触发异常解卷操作的含义是什么?我在文档中找不到任何解释。@qqq如果T.S.投票赞成复制,而另外两个投票赞成离题,那就算作T了。