С#/Java "Try/Finally/Catch" эквивалентная конструкция в Delphi

В Delphi, как вы можете использовать try, наконец, и поймать вместе? Эквивалент Java/С# выглядит примерно так:

try {
    // Open DB connection, start transaction
} catch (Exception e) {
    // Roll back DB transaction
} finally {
    // Close DB connection, commit transaction
}

Если вы попробуете это в Delphi, вы можете использовать try/finally или try/except; но никогда все три вместе. Я бы хотел, чтобы код выглядел следующим образом (который не компилируется):

try
    // Open DB connection, start transaction
except on e: Exception do
begin
    // Roll back transaction
end
finally // Compiler error: expected "END" not "finally"
begin
    // Commit transaction
end

Ответы

Ответ 1

В Delphi вы можете использовать следующий шаблон:

// initialize / allocate resource (create objects etc.)
...
try
  try
    // use resource
    ...
  except
    // handle exception
    ...
  end;
finally
  // free resource / cleanup
  ...
end

Ответ 2

написать

try 
  // allocate resource here
  try 
  finally
    // free resource here
  end;
except
  // handle exception here
end;

Ответ 3

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

procedure Read(Connection: TDBConnection);
begin
  try
    //Read DB
  except
    //Handle Exception
  end;
end;

procedure ReadRecord;
begin
  DBConnection.Open;
  Read(DBConnection);
  DBConnection.Close;
end;

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

Подождите! Как насчет open и close? Что делать, если они вызывают исключения?

Simple. Оберните эти операции в try... кроме функций и обработайте их. Это не обязательно. Если библиотека БД, используемая вами для использования, является чем-то исключением в open или close, не оставит соединение в неизвестном состоянии. Опять же, исключения существуют для вещей, которые вы не ожидаете.

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

Есть, конечно, служебные вызовы функций, но в большинстве случаев они ничтожны, а ваши функции обработки ошибок должны быть достаточно малы, чтобы компилятор мог объединить их.