【问题标题】:Is finally block in C# a must?C# 中的 finally 块是必须的吗?
【发布时间】:2012-03-31 19:27:21
【问题描述】:

两个条件有什么区别?每次运行method1或method2时,都应该有一个代码块需要运行。在我看来,这两种方法是一样的。

// example method1
void Method1(void)
{
    try
    {
        // do something
    }
    catch (Exception ex)
    {
        // do something
    }
    finally
    {
        // do something whenever method1 runs
    }
}

// example method2
void Method2(void)
{
    try
    {
        // do something
    }
    catch (Exception ex)
    {
        // do something
    }

    // do something whenever method2 runs
}

对我来说,最后阻止似乎是不必要的。

【问题讨论】:

  • 您需要具体了解do somethings 才能提出这个问题。
  • 取决于“做某事”的作用
  • 请阅读以下内容以获取更多信息。最后是可选的,您可以在所有处理完成后释放资源。 msdn.microsoft.com/en-us/library/fk6t46tz(v=vs.71).aspx
  • 您在 Method2 中的异常意味着您可能永远无法到达该方法的末尾。在方法 1 中 finally 将始终运行。未发布为答案,因为我会让其他人给出示例等。
  • 不要抓住你不能处理的东西

标签: c# finally


【解决方案1】:

如您所知,编写在 finally 块中的代码始终运行。 请看下面写的以下几点,它将消除您的所有困惑。

  1. 最后用于资源管理。主要用于释放资源。它始终独立于异常运行。
    1. 众所周知,catch 用于处理异常,但有时它无法处理外部异常然后 finally 块用于处理该异常以执行操作。

【讨论】:

    【解决方案2】:

    在您的第一个示例中,您可以重新抛出异常,并且 finally 中的代码仍然会运行。这在第二个示例中是不可能的。

    如果您选择不重新抛出异常,那么是的,差别不大。但是,这被认为是错误的形式 - 如果您需要处理无法显式处理的异常很少 /em>

    它是一个帮助您处理代码执行流程的关键字。当您抛出异常时,代码的执行流程会受到影响(例如使用 return),finally 关键字允许您表示当异常发生时(或者您仍然想要 return 来自 try)执行以在它离开时做某事。

    要开玩笑地回答这个问题,当你需要它而不是当你不需要它时,它是必须的。


    进一步阅读

    为了安全起见,在您尝试开始使用此关键字之前,请阅读它的文档:

    http://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx

    以及一般的异常处理关键字:

    http://msdn.microsoft.com/en-us/library/s7fekhdy.aspx


    示例

    捕获一个异常来处理它,然后重新抛出它。使用finally调用任何整理代码:

    try
    {
        OpenConnectionToDatabase();
        // something likely to fail
    }
    catch (Exception ex)
    {
        Log(ex);
        throw;  
        // throw ex; // also works but behaves differently
    }
    // Not specifying an exception parameter also works, but you don't get exception details.
    //catch (Exception)
    //{
    //    Log("Something went wrong);
    //    throw;
    //}
    finally
    {
        CloseConnectionToDatabase();
    }
    

    不要对捕获异常感兴趣,而是使用finally 来整理代码:

    try
    {
        OpenConnectionToDatabase();
        // something likely to fail
    }
    finally
    {
        CloseConnectionToDatabase();
    }
    

    从您的try 返回,因为它看起来格式很好,但仍然使用finally 来整理代码:

    try
    {
        OpenConnectionToDatabase();
        return 42;
    }
    finally
    {
        CloseConnectionToDatabase();
    }
    

    【讨论】:

    • 嗯,是的,也不是。我有大量的 catch(rethrow 基类中的场景-调用日志接口以将异常写入应用程序日志。即使 IF 进一步处理,我也想一直了解诸如数据库异常之类的东西。
    • @TomTom 它们没有被消耗,它们被观察然后传播。我所说的消耗是指被吞下,再也见不到了。
    • @AdamHouldsworth 他清楚地知道最终做了什么,但不明白他为什么需要它。我想这会对他有所帮助。远不止“阅读规范”。
    • @AdamHouldsworth 很抱歉建议您如何改进您的答案。我正在努力帮助人们。我看到你删除了有问题的评论。抱歉,我不是故意触动神经的。
    【解决方案3】:

    您不一定非得拥有finally 块,但是拥有它可以保证其中的代码将始终运行(除非finally 中出现异常!)。

    考虑以下几点:

    void Method2(void) 
    { 
        try 
        { 
            // do something 
        } 
        catch (Exception ex) 
        { 
            // do something 
            throw;
        } 
    
        // do something whenever method2 runs 
    } 
    

    如果抛出异常,try/catch 之后的代码将不会执行。此外,如果 catch 块中的代码有错误导致异常(例如您的日志记录引发意外异常),则应该在 finally 中的代码将不会运行,保留和清理撤消。

    另外,return 语句将导致该代码不运行,而 finally 仍将被执行(此外,在这里您可以看到 catch 也可以跳过,允许任何异常向上传播 - 在执行finally):

    void Method2(void) 
    { 
        try 
        {  
            // do something
            return
        } 
        finally
        {     
            // do something whenever method2 runs 
        }
    } 
    

    如果您有必须在方法结束时运行的清理代码,请使用finally(或者如果您的对象实现IDisposable,请使用using 语句)。

    【讨论】:

      【解决方案4】:

      最大的不同是 try...catch 会吞下异常,隐藏发生错误的事实。 try..finally 将运行您的清理代码,然后异常将继续运行,由知道如何处理它的东西处理。

      【讨论】:

        【解决方案5】:

        finally 块确保其中的任何代码总是被执行,因此如果您的 try 块中有 return 语句或在 catch 块中重新抛出异常,finally 块中的代码将始终执行。

        如果您需要确保无论如何都会发生某些事情(例如处置资源等),这是必须的

        【讨论】:

          【解决方案6】:

          例如,这将取决于您是 return 还是 try,其行为会非常不同。此外 - 即使catch 抛出异常(或重新抛出原始异常),finally 也会运行,如果没有 finally,这将不会发生。

          所以:它不是必需的,但它的行为会有所不同。因此,如果您希望代码发生,请将其放在 finally 中。

          在许多方面,try/finallytry/catchtry/catch/finally 更常见。

          【讨论】:

            【解决方案7】:

            finally块中的代码在try-catch之后无论如何都会运行,这对于清理非常有用。

            try
            {
                // open resources
            }
            catch (Exception ex)
            {
                // something bad happened
            }
            finally
            {
                // close resources that are still opened
            }
            

            【讨论】:

              猜你喜欢
              • 2011-08-29
              • 1970-01-01
              • 1970-01-01
              • 2014-09-11
              • 2015-04-28
              • 2016-08-15
              • 2021-04-30
              • 2012-05-12
              • 1970-01-01
              相关资源
              最近更新 更多