如何在C#中使用try-finally结构?

4
我们在这个论坛上看到了很多关于try-catch-finallytry-finally结构的问题,答案的数量增加了问题的数量,所以我也有一些问题。
这是一个链接到微软解释try-finally结构的链接。我已经阅读过它!
在下面的文章中写道:
在处理异常时,相关的finally块保证会被执行。然而,如果异常未被处理,finally块的执行取决于异常展开操作如何被触发。这又取决于计算机的设置。
1.我是否正确理解,在try-catch-finally结构中,finally将始终被执行?(不包括Environment.FastFail()
我在这个论坛上读到了关于StackOverFlowException的内容(即在这种情况下finally块不会被执行),但是当我throw它时,finally块会被执行。那么StackOverFlowException是怎么回事?
2.为什么finally块没有被调用?(在下面的代码中)
3.我们通常在哪些情况下使用try-finally
4.finally块依赖于哪些计算机设置?
using System;
namespace ConsoleApplication1
{
class Program
    {
    static void Main(string[] args)
        {
            try
            {
                throw  new Exception(); 
            }                              
            finally
            {
                Console.WriteLine("finally");
                Console.ReadKey();
            }
        }
    }
}    

2
这是4.5个问题;很可能会因为过于宽泛而被关闭。 - Roger Lipscombe
通常情况下,finally块总是会被执行,因此您可以使您的对象释放并关闭所有可能存在的内存泄漏。至于关于计算机配置的问题,我不清楚... - Elty
这个论坛不想成为一个论坛。 - bommelding
这个 finally 块应该会运行。你知道如何在调试器中继续执行吗? - bommelding
3个回答

6
  1. 通常情况下,如果你没有像使用Environment.Exit(0)Application.Exit()这样的方法来中止执行(如Common Man在他的回答中提到的),那么finally块将始终被执行。

    对于StackOverFlowException和其他深层应用程序崩溃,当堆栈已满时,该线程中没有剩余内存执行任何正常操作,因此当您自己抛出异常时,没有真正的完整堆栈,应用程序可以继续运行。

  2. 调试器不会调用finally块,因为如果顶级存在未处理的异常,则调试器会立即关闭,因为没有顶级异常处理程序。请参阅此答案以获取更深入的解释。如果不附加调试器运行应用程序,则将调用finally块-感谢bommelding找出了这一点。

  3. 每次需要确保正确清理时,都要使用finally块。请参阅此答案以获取更深入的解释。

  4. 这是一个棘手的问题,我认为这意味着PC设置的影响,例如病毒扫描程序在尝试创建缓冲区溢出或类似的可能关键情况时终止程序。同样,数据执行预防或其他安全功能可能会阻止执行finally块。


重申第二个问题:它肯定应该可以运行。 - bommelding
@bommelding 我一开始也是这么想的 - 但不,它不会运行 - 请参考链接的答案并尝试自己运行。它不能运行。 - Christoph Sonntag
好的,调试器里它跑不起来,是我的问题。按下Ctrl+F5,然后选择“关闭程序”。你会看到“finally”。 - bommelding
你说得对,这很有趣。我会相应地编辑我的答案。 - Christoph Sonntag

0

1.我是否正确理解,在try-catch-finally结构中,finally块总是会被执行?(除了Environment.FastFail()

在一些特殊情况下,如果首先调用了System.exit()或者虚拟机崩溃,那么finally块将不会被执行。

2.为什么finally块没有被调用?(参考下面的代码)

请阅读这里:finally块可以被中断/暂停吗?

  1. 我们通常在哪些情况下使用try-finally?

try{} finally{}应该在无法处理异常但需要清理资源的情况下使用。

或者在程序中出现异常时,展示一些信息并优雅地退出总是更好的选择。


0

1 - 这取决于情况。使用 finally 块的想法是清理在 try 块中分配的资源,即使在 try 块中发生异常,您也可以在 finally 块中运行代码。然而,finally 块保证在已处理的异常内运行。如果异常未被处理,finally 的执行取决于异常展开操作的触发方式。

2 - 因为异常未处理,所以不会调用您的 finally。Microsoft 文档指出:“通常,在未处理的异常终止应用程序时,是否运行 finally 块并不重要。但是,如果在这种情况下必须运行 finally 块中的语句,则一种解决方案是将 catch 块添加到 try-finally 语句中。”请参阅 https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-finally 中的示例,以查看已处理的异常和未处理的异常之间的差异。

阅读更多关于此问题的信息:为什么要在 C# 中使用 finally?

来源 https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/try-finally https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/try-catch-finally


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接