试试后终于没有打电话了

Fr3*_*dan 3 c# exception-handling try-finally

出于某种原因,在我的控制台应用程序中,我无法运行我的finally块.我正在编写此代码来测试finally块的工作方式,因此非常简单:

static void Main()
{
    int i = 0;
    try
    {
        int j = 1 / i; // Generate a divide by 0 exception.
    }
    finally
    {

        Console.Out.WriteLine("Finished");
        Console.In.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

起初我遇到了这里描述问题,但后来我尝试在Visual Studio外部运行程序我得到了"程序已停止响应"错误.

Pol*_*fun 11

因为您没有顶级异常处理程序,所以.Net运行时正在为您捕获异常并在最终有机会运行之前中止该程序.这说明了这一点:

static void Main() 
{
  try
  {
      int i = 0;
      try
      {
         int j = 1 / i; // Generate a divide by 0 exception.
      }
      finally
      {
          Console.Out.WriteLine("Finished");
          Console.In.ReadLine();     
      }
  }
  catch (Exception ex)
  {
      Console.WriteLine(ex.ToString());
  }
}
Run Code Online (Sandbox Code Playgroud)

使用这段代码,异常现在处理了一个try ...在调用链中捕获更高的位置(它恰好在同一个方法中),因此最终将执行嵌入式.catch不需要在引发异常的同一函数中,它可以在调用链中的任何位置.

编辑:最初可能看起来不确定您的程序将捕获异常的时间和地点.但要考虑应用程序的界限,外部世界与您的代码交互 - 通常它们是有限的并且定义良好.因此,对于控制台应用程序,边界是Main方法,这是您可以放置​​顶级异常处理程序的地方.对于Web表单应用程序,边界包括按钮单击事件(用户正在与UI交互)之类的内容,因此您也可以在其中使用异常处理程序.对于类库,边界通常是调用库的应用程序的边界,而不是库本身.所以不要在库中捕获异常(除非你可以明智地从它们中恢复),但是让它们冒泡到调用应用程序.


Jen*_*ens 3

想在这里添加我自己的发现,因为这里的行为肯定很奇怪 - 因此,接受的答案并不完全正确。

给出以下示例:

static void Main(string[] args)
{
    try{
        throw new Exception("");
    } finally {
        Console.WriteLine("I am never called!");
        Console.ReadLine();
    }
}

Run Code Online (Sandbox Code Playgroud)

如果我们选择从 Windows 错误报告对话框中取消,finally 块实际上会被执行,如下所示:

Windows 错误报告正在进行中 完成后控制台

但是,如果我们允许 Windows 错误报告对话框“完成”,因此我们可以选择“调试”或“关闭程序”,则不会执行 finally 块。

在此输入图像描述 在此输入图像描述


对我来说,这表明.NET运行时实际上会运行所有finally块,无论遇到“未处理的顶级异常”,并且阻止它这样做的实际上是Windows(如果您选择“关闭程序”)或Visual Studio 调试器(如果您选择“调试”或在附加调试器的情况下启动)...因为它们会在运行时之前终止进程作为继续的机会。

有什么想法吗?