编程没有“终于”

时间:2013-12-25 22:00:56

标签: php try-catch-finally

我没有支持finally的所需PHP版本,所以我想知道是否:

try {
    work();
} catch (Exception $e) {
    cleanup();
    throw $e;
}

cleanup();

完全

相同
try {
    work();
} finally {
    cleanup();
}

4 个答案:

答案 0 :(得分:5)

finally块的要点是执行,无论try块中发生了什么,或者跟随catch个案例。因此,如果您考虑一下,finally块中的代码可以在成功执行try块之后执行,也可以在抛出任何异常之后执行。因此,如果您像在解决方案中那样编写它,那么您确实完全模仿了这种情况。如果没有异常,则执行try/catch结构之后的代码;如果有异常 - 任何异常 - 你也会执行它。

我认为finally支持可以拯救你的唯一情况是,你的版本本身不能,就是你实际上在早期中止外部执行堆栈。例如,如果此代码在函数内部并且您从try块内返回,那么finally仍将执行,但在您的手动实现中它当然不能执行。

因此,如果你确保不早退,那么是的,它应该以同样的方式工作。

没有很多方法可以提前保留一个不抛出异常的函数; return是最明显的,并且exitdie或类似的计划会被另一个程序中止。

答案 1 :(得分:4)

最后代码块总是执行 - 如果有异常,如果没有则。但是如果你捕获一个异常并在catch块之后执行cleanup(),那么是 - 它基本上是相同的。

答案 2 :(得分:1)

来自PHP docs

  

在PHP 5.5及更高版本中,也可以在catch块之后指定finally块。 finally块中的代码将始终在try和catch块之后执行,无论是否抛出异常,并且在正常执行恢复之前。

如果查看这些示例,您会注意到即使捕获到异常,finally块也将始终执行。但是,当存在异常时,代码将不会恢复,因此finally块是确保即使存在异常也始终执行某些代码行的好方法。

如果finally阻止使用catch功能或类似功能,return阻止将很重要。否则,将您的清理放在finally区块或try/catch

之后没有区别

以下是文档评论中的相关示例:

  

只是一个例子,为什么finally块有用(5.5)

<?php

//without catch
function example() {
  try {
    //do something that throws an exeption
  }
  finally {
    //this code will be executed even when the exception is executed
  }
}

function example2() {
  try {
     //open sql connection check user as example
     if(condition) { 
        return false;
     }
  }
  finally {
    //close the sql connection, this will be executed even if the return is called.
  }
}

?>

答案 3 :(得分:0)

一般来说,是的。

大多数时候,这两个例子都是等效的:

<?php
function work_success() {
    echo 'working' . PHP_EOL;
}

function work_fail() {
    echo 'working with fail' . PHP_EOL;
    throw new Exception('exception');
}

function cleanup() {
    echo 'cleanup' . PHP_EOL;
}

没有finally的代码:

try {
    work();
} catch (Exception $e) {
    cleanup();
    throw $e;
}
cleanup();

代码finally

try {
    work();
} finally {
    cleanup();
}

work = work_success和非finally版本的finally结果:

working
cleanup

work = work_fail和非finally版本的finally结果:

working
cleanup
Exception: exception

然而,有一些警告。

就像@poke所说的那样,将你的例子与控制流机制一起使用可能会得到有趣的结果。以下是使用简单return语句的说明:

function test()
{
    try {
        return 'success';
    } catch (Exception $e) {
        cleanup();
        throw $e;
    }
    cleanup();
}

echo test();

这将只输出success。除非抛出异常,否则cleanup()不会被触发。根据先前的示例,与上述示例相对应的等效finally将如下所示:

function test()
{
    try {
        return 'success';
    } finally {
        cleanup();
    }
}

echo test();

请注意,无论出现任何异常,此都会执行cleanup(),因此输出将为:

cleanup
success

对于某些人来说,finally块中的代码在return语句之前执行是令人惊讶的。只要你意识到这一点,就应该没有问题。