В каких случаях @finally не является избыточным в обработке исключений в какао try / catch / finally? - PullRequest
9 голосов
/ 12 апреля 2009

Рассмотрим следующие фрагменты кода Какао / Obj-C:

MyClass *obj;
@try {
    [obj doSomething];
}
@catch (NSException * e) {
    NSLog(@"Exception occurred: %@", [e description]);
}
@finally {
    [obj cleanUp];
}

и

MyClass *obj;
@try {
    [obj doSomething];
}
@catch (NSException * e) {
    NSLog(@"Exception occurred: %@", [e description]);
}
[obj cleanUp];

При каких обстоятельствах первый фрагмент будет вызывать [obj cleanUp], а второй не будет вызывать [obj cleanUp]? Другими словами, при каких обстоятельствах @finally не является избыточным при использовании обработки исключений Какао?

Ответы [ 5 ]

15 голосов
/ 12 апреля 2009

В этих сценариях нет разницы, потому что исключение проглочено. Вот два сценария, где есть разница:

[obj cleanUp] называется:

MyClass *obj;
@try {
    [obj doSomething];
}
@catch (NSException * e) {
    @throw;      
}
@finally {
    [obj cleanUp]; // called when exception is caught
}

[obj cleanUp] не вызывается:

MyClass *obj;
@try {
    [obj doSomething];
}
@catch (NSException * e) {
    @throw;
}
[obj cleanUp]; // not called when exception is caught
7 голосов
/ 10 ноября 2010

Стоит также отметить, что код в блоках @finally будет запускаться при выходе из блока @try 1003 * по любой причине даже через return или goto. Например:

@try {
    doStuff();
    if(bail){
        return;
    }
    doMoreStuff();
}
@finally {
    [obj cleanUp];
}
[obj announceSuccess];

[obj cleanUp] будет выполняться, даже если bail истинно, но [obj announceSuccess] не будет.

5 голосов
/ 12 апреля 2009

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

Стоит также указать на один случай, когда вам не нужно использовать @finally, когда вы настраиваете свой собственный пул автоматического выпуска. Когда «родительский» пул автоматического выпуска будет уничтожен, любые внутренние, которые еще не были очищены, также будут. Если вы попытаетесь очистить его самостоятельно, вам нужно продвинуть само исключение из пула авто-релизов.

1 голос
/ 12 апреля 2009

Когда:

  • Вы не уловили тип возникшего исключения
  • Вы поймали исключение, но код в блоке catch также выдает исключение.
0 голосов
/ 13 апреля 2009

Вопрос более низкого уровня, почему вы это делаете?

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

Наиболее широко используемым и понятным соглашением является соглашение о делегате, у которого есть обратный вызов метода ошибки или, возможно, уведомления о более общих ошибках, которые необходимо пропустить через несколько уровней кода. Этот подход мог бы более широко использоваться в мире Java, если бы существовала простая система уведомлений, как это было в Cocoa.

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

...