Будет ли пытаться / наконец (без улова) пузырь исключение?


Я почти уверен, что ответ-да. Если я использую блок Try Finally, но не использую блок Catch, то любые исключения будут пузыриться. Правильно?

какие-нибудь мысли о практике в целом?

сет

2 93

2 ответа:

Да, это обязательно. Предполагая, что ваш finally блок не бросает исключение, конечно, в этом случае это будет эффективно "заменить" тот, который был первоначально брошен.

есть мысли о практике в целом?

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

в этой ситуации, возможно, дело в том, что вы не должны запускать код наконец блокирует вообще. Код в блоке finally можно было бы предположить, что это зависит от подсистемы здоровы, когда на самом деле они могут быть глубоко нарушена. Код в блоке finally может ухудшить ситуацию.

например, я часто вижу такие вещи:

DisableAccessToTheResource();
try
{
    DoSomethingToTheResource();
}
finally
{
    EnableAccessToTheResource();
}

автор этого кода думает:"я делаю временную мутацию в состояние мира; мне нужно восстановить состояние, в котором оно было до того, как меня назвали". Но давайте подумаем обо всем способов это может пойти не так.

во-первых, доступ к ресурсу уже может быть отключен абонентом; в этом случае разрешает код это, возможно, преждевременно.

во-вторых, если DoSomethingToTheResource выдает исключение, правильно ли это сделать, чтобы разрешить доступ к ресурсу??? Код, который управляет ресурсом неожиданно разбилось. Этот код говорит, по сути "если код управления нарушен,убедитесь, что другой код может вызвать что сломанный код как можно скорее, так что он может потерпеть неудачу ужасно слишком.- Похоже, это плохая идея.

В-третьих, если DoSomethingToTheResource выдает исключение, то как мы узнаем, что EnableAccessToTheResource также не будет выдавать исключение? Независимо от того, что случилось с использованием ресурса, это может также повлиять на код очистки, и в этом случае исходное исключение будет потеряно, и проблема будет сложнее диагностировать.

Я обычно пишу такой код без использование try-finally блоков:

bool wasDisabled = IsAccessDisabled();
if (!wasDisabled)
    DisableAccessToTheResource();
DoSomethingToTheResource();
if (!wasDisabled)
    EnableAccessToTheResource();

Теперь состояние не мутирует, если это не нужно. Теперь состояние вызывающего абонента не перепутано. И теперь, если DoSomethingToTheResource не удается, то мы не повторно включить доступ. Мы предполагаем, что что-то глубоко сломано и не рискуем ухудшить ситуацию, пытаясь продолжать работать с кодом. Пусть звонящий разбирается с проблемой, если они могут.

Так когда это хорошая идея, чтобы запустить наконец блок? Во-первых, когда исключение ожидаемый. Например, вы можете ожидать, что попытка заблокировать файл может завершиться неудачей, потому что кто-то другой заблокировал его. В этом случае имеет смысл поймать исключение и сообщить пользователю. В этом случае неопределенность в отношении того, что сломано, уменьшается; вы вряд ли сделаете все хуже, очистив.

во-вторых, когда ресурс, который вы очищаете, является дефицитным системным ресурсом. Например, имеет смысл закрыть дескриптор файла в блоке finally. ("Использование" имеет конечно, просто еще один способ написания try-finally block.) Содержание файла может быть поврежден, но вы ничего не можете с этим поделать. Дескриптор файла будет закрыт в конечном итоге, так что это может быть скорее раньше, чем позже.