Могу ли я использовать try-catch-finally как это?

Я использую try-catch в течение многих лет, но я никогда не узнали, как и когда использовать finally, потому что я никогда не понимал точки finally (Я читал плохие книги)?

Я хочу спросить вас об использовании finally в моем случае.

мой пример кода должен все объяснить:

$s = "";

$c = MyClassForFileHandling::getInstance();

try
{
    $s = $c->get_file_content($path);
}

catch FileNotFoundExeption
{
    $c->create_file($path, "text for new file");
}

finally
{
    $s = $c->get_file_content($path);
}

это правильное использование наконец?

более конкретный вопрос:

использовать finally (в будущих версиях PHP или других языках) для обработки " создать что-то, если оно не существует" операции?

4 ответов


Finally всегда будет выполняться, поэтому в этом случае это не является его предназначением, так как нормальное выполнение откроет файл во второй раз. То, что вы намереваетесь сделать, будет достигнуто тем же (более чистым) способом, если вы это сделаете

$s = "";

$c = MyClassForFileHandling::getInstance();

try
{
    $s = $c->get_file_content($path);
}
catch(FileNotFoundExeption $e)
{
    $c->create_file($path, "text for new file");
    $s = $c->get_file_content($path);
}

тогда руководство говорит:

в интересах кого-то, кто не сталкивался с блоками finally раньше, ключевое различие между ними и обычным кодом после блока try / catch заключается в том, что они будут выполняться даже блок try/catch вернет управление вызывающей функции.

Он может сделать это, если:

  • код, если ваш блок try содержит тип исключения, который вы не поймали
  • вы бросаете другое исключение в свой блок catch
  • ваш try или catch вызовы возвращают

наконец, тогда было бы полезно в таком сценарии:

function my_get_file_content($path)
{
    try
    {
        return $c->get_file_content($path);
    }
    catch(FileNotFoundExeption $e)
    {
        $c->create_file($path, "text for new file");
        return $c->get_file_content($path);
    }
    finally
    {
        $c->close_file_handler();
    }
}

=> Если вам нужно убедиться, что вы закрываете ваш обработчик файлов в этом случае или какой-либо ресурс в целом.


finally не был введен в PHP до версии 5.5, которая еще не была выпущена, поэтому вы еще не видели никаких примеров с ней. Поэтому, если вы не используете альфа-версию PHP 5.5, вы не можете использовать finally пока.

из руководства (исключения)

в PHP 5.5 и более поздних версиях блок finally также может быть указан после блоков catch. Код в блоке finally всегда будет выполняться после попробовать и блоки catch, независимо от того, было ли создано исключение, и до возобновления нормального выполнения.

пример из руководства по использованию finally

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    else return 1/$x;
}

try {
    echo inverse(5) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "First finally.\n";
}

try {
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "Second finally.\n";
}

// Continue execution
echo 'Hello World';
?>

наконец означает, что вы хотите сделать, наконец.

try
{
    $s = $c->get_file_content($path);
}

catch FileNotFoundExeption
{
    $c->create_file($path, "text for new file");
}

finally
{
    //Create a pdf with my file
    //or, Rename my file
    //or, store my file into Database
}

независимо от того, что происходит(независимо от того, было ли вызвано исключение) внутри try или catch, "Finally code" будет выполняться. Таким образом, нет смысла использовать один и тот же код над " try " и "finally". Это просто ответ на ваш вопрос?


Я просто хочу назначить, что если исключение возникает в блоке try блок, исключение будет правильно поднято, даже если finally блок присутствует. Полезность finally блок для чистых и свободных ресурсов. Я думаю, что лучше всего использовать, когда, например, вы загружаете файл, но затем происходит ошибка:

$tmp_name = null;
try {
    $tmp_name = tempnam(UPLOAD_DIR, 'prefix');
    move_uploaded_file($file['tmp_name'], $tmp_name);
    ImageManager::resize($tmp_name, $real_path, $width, $height); // this will rise some exception
}
finally {
    if($tmp_name)
        unlink($tmp_name); // this will ensure the temp file is ALWAYS deleted
}

как вы можете видеть, таким образом, независимо от того, что произойдет, временный файл будет правильно удален.
Если бы мы подражали finally предложение в старом версия PHP, мы должны написать что-то вроде этого:

// start finally
catch(Exception $ex) {
}
if($tmp_name)
    unlink($tmp_name);
if( isset($ex) )
    throw $ex;
// end finally

обратите внимание, что исключение было повторно брошено в случае catch заблокировать что-то поймал. Это не ясно, как finally версия, но работает так же.