【问题标题】:Use a 'try-finally' block without a 'catch' block使用没有“catch”块的“try-finally”块
【发布时间】:2012-03-06 16:18:57
【问题描述】:

在没有catch 块的情况下,是否适合使用try-finally 块?

【问题讨论】:

  • 在 MSDN 上,请参阅 try-finally (C# Reference)。请注意,文章将tryfinally 的组合使用称为“try-finally statement”。

标签: c# .net exception exception-handling


【解决方案1】:

1. 我们可以不使用 catch 使用 try 块,但我们应该使用 catch/finally, 其中任何一个。 2.我们不能只使用try块。

【讨论】:

    【解决方案2】:

    在这种情况下,您可能希望使用 try finally:当您通常使用 using 语句,但由于您通过反射调用方法而不能使用时。

    这行不通

    using (objMsg  =  Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("omApp.MessagingBO")))
    {
    
    }
    

    改为使用

               object objMsg = null;
                try
                {
                    objMsg
                       = Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("myAssembly.objBO"));
    
                    strResponse = (string)objMsg.GetType().InvokeMember("MyMethod", BindingFlags.Public
                            | BindingFlags.Instance | BindingFlags.InvokeMethod, null, objMsg,
                            new object[] { vxmlRequest.OuterXml });
                }               
                finally
                {
                    if (objMsg!=null)
                        ((IDisposable)objMsg).Dispose();
                }
    

    【讨论】:

      【解决方案3】:

      这是一个我一直(嗯..)使用的用例:

      int? x; //note the nullable type here!
      try
      {
          x = int.Parse(someString);
      }
      catch { } //don't care, let it just be null
      

      【讨论】:

        【解决方案4】:

        用代码很好的解释:

        void MyMethod1()
        {
            try
            {
                MyMethod2();
                MyMethod3();
            }
            catch(Exception e)
            {
                //do something with the exception
            }
        }
        
        
        void MyMethod2()
        {
            try
            {
                //perform actions that need cleaning up
            }
            finally
            {
                //clean up
            }
        }
        
        
        void MyMethod3()
        {
            //do something
        }
        

        如果 MyMethod2 或 MyMethod3 中的任何一个抛出异常,它将被 MyMethod1 捕获。但是,MyMethod2 中的代码需要运行清理代码,例如在将异常传递给 MyMethod1 之前关闭数据库连接。

        http://forums.asp.net/t/1092267.aspx?Try+without+Catch+but+with+finally+doesn+t+throw+error+Why+no+syntax+error+

        【讨论】:

        • 这种“清理”的例子可能是 saveLogFile(),无论如何我都想把它放在程序的最后。
        【解决方案5】:

        您可以使用它来确保在 try 内容之后或在异常时发生某些操作,但是当您不希望使用该异常时。

        需要明确的是,这不会隐藏异常。 finally 块在异常向上传播到调用堆栈之前运行。

        当您使用using 关键字时,您也会无意中使用它,因为这会编译成try-finally(不是精确转换,但为了论证,它已经足够接近了)。

        try
        {
            TrySomeCodeThatMightException();
        }
        finally
        {
            CleanupEvenOnFailure();
        }
        

        不能保证在finally 中运行的代码可以运行,但是不能保证的情况是相当先进的——我什至不记得了。我只记得,如果你在这种情况下,很有可能不运行finally 不是你最大的问题:-) 所以基本上不要出汗。

        来自 Tobias 的更新:如果进程被杀死,finally 将不会运行。

        来自 Paddy 的更新: Conditions when finally does not execute in a .net try..finally block

        您可能会看到的最普遍的例子是即使代码失败也会处理数据库连接或外部资源:

        using (var conn = new SqlConnection("")) // Ignore the fact we likely use ORM ;-)
        {
            // Do stuff.
        }
        

        编译成 something 比如:

        SqlConnection conn;
        
        try
        {
            conn = new SqlConnection("");
            // Do stuff.
        }
        finally
        {
            if (conn != null)
                conn.Dispose();
        }
        

        【讨论】:

        • @AnthonyBlake 没有隐藏异常。如果发生异常,它将运行 finally,然后将异常传播回调用堆栈。
        • 对于边缘情况,如果进程被杀死(例如,在任务管理器中使用“终止进程”或由于断电),finally 将不会运行。
        • 有关 finally 语句何时不会触发的更多信息 - 不仅仅是在进程被终止时:stackoverflow.com/questions/111597/…
        • 另一个不是 all 的 finally 将运行的明显情况是,如果在 finally 块中发生错误。
        • 最后不会在我能想到的三种场景中调用:杀死进程、堆栈溢出、内存不足。所有这些基本上都会在遇到它们的确切点停止程序的执行,并向操作系统发出终止进程的信号。
        【解决方案6】:

        using 等价于 try-finally。当您想在finally 内部进行一些清理并且不关心异常时,您只会使用try-finally

        最佳方法将是

        try
        {
           using(resource)
           {
               //Do something here
           }   
        }catch(Exception)
        {
             //Handle Error
        }
        

        这样做即使using 调用的清理失败,您的代码也不会失败。

        finally 在某些情况下不会被执行。

        • 如果有StackOverflowExceptionExecutingEngineException
        • 进程被外部源杀死。

        希望这能解答您的疑问。

        【讨论】:

          【解决方案7】:

          我对 C# 一无所知,但似乎你可以用 try-finally 做的任何事情,你都可以更优雅地用 using statement 做。 C++ 甚至没有finally as a result of its RAII

          【讨论】:

          • 不一定。如果您想运行一些无法通过简单处理来处理的自定义代码怎么办。例如,如果你在try 中增加一个计数器,然后在finally 中减少它,你不能在using 语句中这样做。
          • @MarkA.Donohoe 你能不能创建一个对象来保存对计数器的引用,当它被释放时它会递减?
          • 是的,但是为什么要创建一个完整的对象只是为了实现一个一次性接口以与 using 语句一起使用?这使问题适合解决方案。 Try-[Catch]-Finally 可以处理所有这些,而无需创建这样的对象。
          • @MarkA.Donohoe 对象解决方案非常出色,因为它在一个地方实现了包围模式。您不能忘记、放错位置或意外删除递减代码。
          • 对不起,我不同意。您专注于显式递减行为,但谁说它们必须完美匹配?如果还有其他递增/递减逻辑也依赖于函数中的其他成员怎么办?另外,您现在不仅要引入一个新对象仅用于一种用途,而且您是在堆上这样做而不是在堆栈上使用简单的 int。肯定有时间和地点可以使用using,但你不能像你一样做出一揽子声明。同样,这是通过解决方案来定义问题,对我来说这是倒退的。
          【解决方案8】:

          例如,如果您有一个在 try 块中创建和使用的非托管资源,则可以使用 finally 块来确保释放该资源。尽管 try 块中发生了什么(例如异常),finally 块将始终执行。

          例如lock(x) 语句真的是:

          System.Threading.Monitor.Enter(x); 
          try { ... } 
          finally 
          { 
              System.Threading.Monitor.Exit(x); 
          } 
          

          总是会调用 finally 块以确保释放排他锁。

          【讨论】:

            【解决方案9】:

            看看下面的链接: https://softwareengineering.stackexchange.com/questions/131397/why-use-try-finally-without-a-catch-clause

            这取决于您的应用程序的架构以及您在块中执行的操作。

            【讨论】:

              【解决方案10】:

              try/finally:当您不想处理任何异常但想确保某些操作发生时,无论调用代码是否抛出异常。

              【讨论】:

                【解决方案11】:

                你需要一个 finally 块,当无论哪个(如果有)异常被捕获,或者即使没有被捕获,你仍然希望在块退出之前执行一些代码。例如,您可能想要关闭一个打开的文件。

                另见try-finally

                【讨论】:

                  猜你喜欢
                  • 2011-06-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-09-05
                  • 2011-08-31
                  • 2013-12-16
                  • 1970-01-01
                  • 2018-11-07
                  • 1970-01-01
                  相关资源
                  最近更新 更多