【问题标题】:Initializing disposable resources outside or inside try/finally在 try/finally 外部或内部初始化一次性资源
【发布时间】:2009-01-20 20:47:00
【问题描述】:

我见过两种获取和处置资源的方法。要么:

Resource resource = getResource();
try { /* do something with resource */ }
finally { resource.close(); }

或:

Resource resource = null;
try { resource = getResource(); /* do something with resource */ }
finally { if (resource != null) resource.close(); }

我想知道哪种风格更可取。第一个避免了if 条件,而第二个(我认为)在分配之后但在进入try 块之前处理线程中止的情况。这些风格彼此之间还有哪些其他优点和缺点?我应该优先使用哪一个?

【问题讨论】:

    标签: c# java coding-style resources


    【解决方案1】:

    在 C# 中,只需使用 using 语句:

    using (Resource resource = GetResource())
    {
        /* Do something */
    }
    

    这是清理资源的惯用方式,并且依赖于实现IDisposable 接口的相关资源。 (Java 现在有一个类似的 try-with-resources 语句,用于实现 AutoCloseable 的资源。)

    在分配和进入 try 块之间没有发生 Java 中线程中止的风险 - 中止仅在睡眠和等待期间发生。编辑:我实际上在规范中找不到这个,这有点令人担忧。嗯。

    【讨论】:

    • 谢谢。 C# 的 using 关键字很棒,但有时不能使用(例如,对于不实现 IDisposable 的类型,或者应有条件地调用 Dispose() 时)。至于Java,我没有实际处理过此类问题的经验,但是不能中断线程吗?
    • 如果您编写代码允许它们可以被(安全地)中断,真正发生的是线程可以收到需要中断的信号,并且在线程代码上您决定如何停止当前正在执行的工作
    • 是的——但至少他们不会在分配后、进入前尝试块时被打断。这是重要的一点:)
    • 请问你怎么知道他们在分配和尝试之间不会被打断?
    • @Hosam:正如我所说,我还没有在规范中找到它,但请注意 InterruptedException 是一个 checked 异常,所以它不能只是被扔到任何地方。我相信某处它被记录为仅在阻塞操作(等待/睡眠/IO等)期间抛出。
    【解决方案2】:

    第一个比较好

    【讨论】:

      【解决方案3】:

      如果 getResource() 抛出异常,则 resource 将为 null,getResource() 在异常情况下不返回任何内容.因此,只要 getResource() 可以抛出异常,请始终在调用 resource.close() 之前检查 null。我觉得组织这段代码的最好方法是将所有内容都放在 try 块中;明确 getResource() 抛出异常。

      【讨论】:

      • 虽然第一个版本没有必要这样做 - 如果抛出异常,您将无法到达 finally 块。
      • 在类似的代码中,例如,正在获取和释放锁,获取失败将导致不匹配的释放。
      猜你喜欢
      • 2021-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-01
      • 2012-12-22
      • 2014-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多