好吧,这是一个奇怪的问题,我希望有人可以解释一下.我有以下代码:
static void Main(string[] args)
{
try
{
Console.WriteLine("in try");
throw new EncoderFallbackException();
}
catch (Exception)
{
Console.WriteLine("in Catch");
throw new AbandonedMutexException();
}
finally
{
Console.WriteLine("in Finally");
Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当我将其编译为目标3.5(2.0 CLR)时,它将弹出一个窗口,说"XXX已停止工作".如果我现在单击取消按钮它将运行finally,如果我等到它完成查找并单击关闭程序按钮它也将运行finally.
现在有趣和令人困惑的是,如果我针对4.0编译同样的事情点击取消按钮将运行finally块并单击关闭程序按钮不会.
我的问题是:为什么在点击关闭程序按钮时,终于在2.0上运行而不在4.0上运行?这有什么影响?
编辑:我在Windows 7 32位的发布模式(内置发布模式)中从命令提示符运行此命令.错误消息:在Windows查找问题后,下面的第一个结果是3.5点击关闭,第二个是我在4.0上运行它并执行相同的操作.
我以为我已经了解 C# 中的异常处理是如何工作的。重新阅读文档以获得乐趣和自信,我遇到了问题:
该文档声称以下两个代码片段是等效的,甚至在编译时将第一个代码片段转换为后一个代码片段。
using (Font font1 = new Font("Arial", 10.0f)) {
byte charset = font1.GdiCharSet;
}
Run Code Online (Sandbox Code Playgroud)
和
{
Font font1 = new Font("Arial", 10.0f);
try {
byte charset = font1.GdiCharSet;
}
finally {
if (font1 != null)
((IDisposable)font1).Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
此外,它还声称:
using 语句确保 Dispose 被调用,即使在您调用对象的方法时发生异常。
相比之下,该文件指出:
在处理的异常中,
finally
保证运行关联的块。但是,如果未处理异常,则finally
块的执行 取决于触发异常展开操作的方式。
我不明白这一点。在第一个文档的代码示例中,异常显然是未处理的(因为没有 catch 块)。现在,如果第二个文档中的语句为真,finally
则不能保证执行该块。这最终与第一个文件所说的(“using
声明确保......”)(强调我的)相矛盾。
那么真相是什么呢?
编辑 1
我还是不明白。StevieB 的回答让我从 C# 语言规范中阅读了更多部分。在 16.3 节中,我们有:
[...] 这种搜索一直持续到找到可以处理当前异常的 catch 子句为止。 …
一个简单的控制台应用程序,在 Visual Studio 2019、.Net Framework 4.7、Windows 中:
static void Main(string[] args)
{
try
{
Console.WriteLine("In try");
throw new IndexOutOfRangeException();
}
finally
{ *// Surprisingly this part is not being executed.*
Console.WriteLine("In finally");
Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud)
我确信在没有异常的情况下以及在有异常的情况下都会调用finally块。我在文档中读到:
但是,如果异常未处理,则finally块的执行取决于异常展开操作的触发方式。反过来,这取决于您的计算机的设置方式。
嗯,我很困惑。我是否需要对这个“展开操作”做一些事情,以便在出现未处理的异常时调用finally?
c# finally try-catch console-application unhandled-exception