【问题标题】:Actual use of finally blockfinally 块的实际使用
【发布时间】:2011-02-21 17:51:55
【问题描述】:

我问了我的朋友这个问题,他说它是用来销毁在异常处理过程中创建的对象。但是在c#GC中是用来销毁这类未使用的对象的,那么finally块的实际用途是什么。告诉我一个与此相关的场景。

【问题讨论】:

标签: c# memory-management idisposable


【解决方案1】:

是一个无论是否发生异常都保证运行的块。

因此,通常情况下,如果您想要确保正确释放某种资源,您会使用它。与 during the exception handling 创建的对象无关。但是假设您有某种与数据库或文件句柄的连接。

如果是实现IDisposable 的托管对象,更好的方法通常是using 关键字。

【讨论】:

    【解决方案2】:

    当它们不再被引用时,GC 将清除 托管 资源(您的应用程序在内存中创建的对象)。这不包括文件句柄、网络资源、数据库连接等...您必须finally 块中自行清除它们,否则可能无法清除它们(尽管大多数最终会清除) .

    ,更常见的是:

    许多要处理的非托管资源的类都实现了IDisposable 接口。这意味着您可以将代码包装在 using 块中,并确保将清除非托管资源(它会在超出范围时调用对象的 Dispose() 方法)。

    使用 finally 块的一个很好的例子是使用 Office 互操作库。假设您打开 Microsoft Word,运行一些代码,代码失败...Word 将总是 需要关闭,无论是否发生错误。因此我会将结束代码放在finally 块中。

    【讨论】:

      【解决方案3】:

      GC 将最终销毁对象,这是真的。但是,当您拥有最好尽快释放的非内存资源时,finally 块很有用。例如,如果你有一个数据库连接,你不希望连接在终结器运行之前保持打开(可能是无限制的)很长时间,所以你把它放在一个 using 块中(这只是语法糖try ... finally 块):

      using(var conn = new SqlConnection(...))
      {
          // use the connection
      }
      

      这是(基本上)的语法糖:

      var conn = new SqlConnection(...);
      try
      {
          // use the connection
      }
      finally
      {
          conn.Dispose();
      }
      

      现在,如果您没有 finally/using,那么当对象的终结器运行时,连接最终会被释放,但因为您不知道那会发生什么发生这种情况时,最好将对象的使用情况包装在 using 块中,以确保不再需要连接时立即关闭。

      【讨论】:

        【解决方案4】:

        finally 用于保证某些操作无论是否发生异常都能执行。

        其中一个用途——尽管不是很“优雅”——是在先前打开的数据库连接上调用 close()。更一般地用于 GC 未清除的所有事物(例如 db 或网络连接)。

        http://msdn.microsoft.com/en-en/library/zwc8s4fz(VS.80).aspx

        【讨论】:

          【解决方案5】:

          finally 块被使用,当你想要一段代码运行时不管是否发生异常。例如关闭数据库连接。

          【讨论】:

            【解决方案6】:

            finally 块不仅仅用于内存释放! 想想这个案例: 在“尝试”中阻止您- 1.打开与数据库的连接 2. 执行查询 第 2 步失败并出现异常。 但是,在任何情况下,您都应该关闭与数据库的连接 - 执行此操作的正确位置是在 finally 块内。

            这只是一个例子。有许多不同的情况可能需要 finally 块。

            【讨论】:

              【解决方案7】:

              垃圾收集器将在适当的时候收集托管资源。对于那些还持有非托管资源(如网络资源、数据库连接或文件句柄等)的人,它们通常支持IDisposable 接口,如果操作正确,仍将通过终结器释放资源;但是通过Dispose()ing 在finally 块中,您可以控制何时这些资源被释放。

              如果您只有一个 IDisposable 对象,那么 using 块可能更合适,尽管如果您 (a) 需要处理块内抛出的异常,或者 (b)有几个 IDisposable 对象一起使用(例如,SqlConnectionSqlCommand...)

              【讨论】:

                【解决方案8】:

                除了提到的其他场景之外,另一种常见的情况发生在锁上。 synclock 语句调用Monitor.Enter 并执行一段代码;然后它使用finally 块调用Monitor.Exit。如果代码在没有调用Monitor.Exit 的情况下离开块,那么任何其他使用锁保护的资源的尝试都将被永远阻止。

                顺便说一句,即使synclock 内部发生了一些不好的事情,以至于被锁保护的资源应该被认为是损坏的并且没有被使用,保持锁被持有也不是处理这种情况的好方法。更好的方法是让同步锁中的代码显式地使对象无效,这样任何其他等待锁的代码都将被授予访问权限,然后在尝试使用无效对象时最终抛出异常。

                【讨论】:

                  猜你喜欢
                  • 2020-02-16
                  • 2013-06-25
                  • 1970-01-01
                  • 2012-03-06
                  • 1970-01-01
                  • 2013-12-16
                  • 2014-01-08
                  • 2017-12-19
                  • 2018-10-28
                  相关资源
                  最近更新 更多