基本上我听说某些条件会导致.net超越finally块.有谁知道这些条件是什么?
好吧,这是一个奇怪的问题,我希望有人可以解释一下.我有以下代码:
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#程序:
namespace dispose_test
{
class Program
{
static void Main(string[] args)
{
using (var disp = new MyDisposable())
{
throw new Exception("Boom");
}
}
}
public class MyDisposable : IDisposable
{
public void Dispose()
{
Console.WriteLine("Disposed");
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我使用它时dotnet run,我看到以下行为:
Windows上的延迟很烦人,但是在Linux上根本没有调用Dispose()的事实令人不安.这是预期的行为吗?
编辑以下对话中的澄清/补充:
using/Dispose(),这只是一个特例try/finally.行为也通常发生try/finally- finally块未运行.我更新了标题以反映这一点.Dispose()通过将文件写入文件系统来执行,只是为了确保问题与stdout Dispose()在未处理的异常情况下运行之前与控制台断开连接无关.行为是一样的.Dispose()如果在应用程序中的任何位置捕获到异常,则会调用它.当应用程序完全未处理时会发生此行为.dotnet run在两个平台上进行的,这意味着单独的编译,但我也试过dotnet publish在Windows上直接运行两个平台上的输出,结果相同.唯一的区别是,当直接在Linux上运行时,在异常文本之后写入"Aborted(core dumped)"文本.版本细节:
dotnet --version - > 1.0.4.我以为我已经了解 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 子句为止。 …