为什么抛出异常时finally块可能不执行?
Why finally block may not execute when exception is thrown?
很长一段时间我认为它可以让我释放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
}
}
}
我从来没有到达打印到控制台的行。这意味着在这种情况下,在 try
块内抛出异常时,我将无法释放 finally
块中的资源。
所以,我相信有两件事:要么是我遗漏了什么,要么是 try
+ finally
组合在 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
}
}
但恐怕我可能在这里遗漏了一些东西。那么,有人可以确认该组合没有用或证明它没有用吗?
更新
在评论可以调用 fiddle 中的 finally
块后,我在 VS Code 中再次检查,但仍然没有看到输出。
您的假设不正确(有时)https://dotnetfiddle.net/hjqmOS
By using a finally block, you can clean up any resources that are
allocated in a try block, and you can run code even if an exception
occurs in the try block. Typically, the statements of a finally block
run when control leaves a try statement. The transfer of control can
occur as a result of normal execution, of execution of a break,
continue, goto, or return statement, or of propagation of an exception
out of the try statement.
有些情况下它不会运行但
Within a handled exception, the associated finally block is guaranteed
to be run. However, if the exception is unhandled, execution of the
finally block is dependent on how the exception unwind operation is
triggered. That, in turn, is dependent on how your computer is set up.
这是重要的部分
Usually, when an unhandled exception ends an application, whether or
not the finally block is run is not important. However, if you have
statements in a finally block that must be run even in that situation,
one solution is to add a catch block to the try-finally statement.
Alternatively, you can catch the exception that might be thrown in the
try block of a try-finally statement higher up the call stack.
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 会显示异常。如果您编译它并在命令行上手动 运行,我相信您会看到 "divide by zero"。此外,您可以 'handle' 错误,而不是更改您的 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");
}
}
}
很长一段时间我认为它可以让我释放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
}
}
}
我从来没有到达打印到控制台的行。这意味着在这种情况下,在 try
块内抛出异常时,我将无法释放 finally
块中的资源。
所以,我相信有两件事:要么是我遗漏了什么,要么是 try
+ finally
组合在 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
}
}
但恐怕我可能在这里遗漏了一些东西。那么,有人可以确认该组合没有用或证明它没有用吗?
更新
在评论可以调用 fiddle 中的 finally
块后,我在 VS Code 中再次检查,但仍然没有看到输出。
您的假设不正确(有时)https://dotnetfiddle.net/hjqmOS
By using a finally block, you can clean up any resources that are allocated in a try block, and you can run code even if an exception occurs in the try block. Typically, the statements of a finally block run when control leaves a try statement. The transfer of control can occur as a result of normal execution, of execution of a break, continue, goto, or return statement, or of propagation of an exception out of the try statement.
有些情况下它不会运行但
Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.
这是重要的部分
Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important. However, if you have statements in a finally block that must be run even in that situation, one solution is to add a catch block to the try-finally statement. Alternatively, you can catch the exception that might be thrown in the try block of a try-finally statement higher up the call stack.
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 会显示异常。如果您编译它并在命令行上手动 运行,我相信您会看到 "divide by zero"。此外,您可以 'handle' 错误,而不是更改您的 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");
}
}
}