很长一段时间以来,我认为它可以释放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
块中的异常。
因此,我相信有两件事:我遗漏了一些东西,或者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
}
}
但是,我担心这里可能会丢失一些东西。那么,请问有人可以确认组合是无用的还是证明不是呢?
更新
在能够调用finally
块的注释之后,我再次在VS Code中进行了检查,但仍然看不到任何输出。
答案 0 :(得分:8)
您的假设是错误的(有时)https://dotnetfiddle.net/hjqmOS
通过使用finally块,您可以清理所有 分配在try块中,即使出现异常也可以运行代码 发生在try块中。通常,finally块的语句 当控件离开try语句时运行。可以转移控制权 因正常执行,执行中断而发生 继续,转到或返回语句,或传播异常 在try语句之外。
在某些情况下它仍然无法运行
在已处理的异常中,可以保证关联的finally块 要运行。 但是,如果未处理异常,则执行 finally块取决于异常展开操作的方式 触发。反过来,这取决于计算机的设置方式。
这是重要的部分
通常,当未处理的异常终止应用程序时,无论是 不是finally块运行并不重要。 但是,如果您有 在即使在这种情况下也必须运行的finally块中的语句, 一种解决方案是在try-finally语句中添加catch块。 或者,您可以捕获可能会在 在调用堆栈上方的try-finally语句的try块。
答案 1 :(得分:1)
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
}
答案 2 :(得分:1)
我相信这是因为您有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");
}
}
}
答案 3 :(得分:0)
我想分享通过CLR 摘录自 C#的以下摘录,这对我来说很清楚,为什么最终块可能不会被调用。
如果在try块(或在try块内调用的任何方法)中执行的代码引发异常,则CLR开始搜索其catch类型与或相同的catch类型的catch块。 引发的异常的基本类型。如果没有任何捕获类型与异常匹配,则CLR继续 在调用堆栈中搜索以查找与异常匹配的捕获类型。如果达到 在调用堆栈的顶部,找不到匹配类型的catch块,未处理的异常 发生。
一旦CLR找到具有匹配catch类型的catch块,它将在所有内部执行代码 最终块,从其代码引发异常的try块开始并停止 与匹配异常的catch块。请注意,与 与异常匹配的catch块尚未执行。最终代码中的代码不会 执行直到处理catch块中的代码执行完。
执行完内部finally块中的所有代码之后,处理catch块中的代码 执行。
因此,这意味着在发生任何未处理的异常的情况下,不会调用 finally (最终)块。