Рассмотрите следующую структуру кода C# (S0-S3 являются заполнителями для блоков произвольного кода):
try
{
S0;
}
catch (Exception ex)
{
S1;
}
finally
{
S2;
}
S3;
В случае, что S1 выдает исключение в catch
обработчик, S2 в finally
все еще выполнится (но S3 не будет).
Предположение, что S1 не может бросить, является там любой точкой в наличии S2 внутри a finally
блок, вместо того, чтобы иметь его вне попытки/выгоды/наконец, незадолго до S3?
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
finally
{
S2;
}
S3;
Есть ли любая точка в наличии finally
блок? Следующее кодировало бы не быть эквивалентным (под строгим предположением это, что в catch
блок не может бросить):
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
// No finally block needed (?)
S2;
S3;
Обновление: Если признано, что эти два блока кода выше эквивалентны (под указанными предположениями) тогда, принимая во внимание обратную связь на ясности кода в ответах, был бы он быть предпочтительным (и эквивалентным) для объединения S2 и S3 в finally
блок?
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
finally
{
S2; // Put S2 and S3 together inside the `finally` block to guard against
S3; // future changes in the `catch` filter, or handling code.
}
Предположение, что S1 не может бросить, является хрупким, учитывая сценарии истощения ресурсов (то есть, у вас нет памяти). Даже если оправдано (большой, если), незначительные изменения в коде могут ввести исключение.
Поскольку S2 обычно обеспокоен уборкой и выделением ценных ресурсов, вкладывая его в наконец-то блокировку, связывает, что намерение четко. Установка такого кода, где это возможно, в Dispose () метод ресурсов, владеющего объектом и замена пункта TRY / Наконец с предложением использования, может сообщить о намерении еще лучше (и более идиоматически для C #).
Всякий раз, когда вы можете написать что-то в два или более разных способах, используйте тот, который является ясным и наиболее стабильным против изменений.
Re Внешний вопрос: S3 должен быть помещен в наконец, если оно касается очистки. Если это предполагает успех блока попробовать, он должен быть размещен после окончательного блока. Если выявление вашего улова не рихроу, я лично интерпретирую это, чтобы означать, что вы преодолели и могли действовать с обычными операциями. Однако все «сохранить исключение, чтобы повторно бросить позже», путает меня. Как правило, я бы посоветовал с сохранением исключения для предшествующих измерений вне метода. Это необычно и кажется запутанным мне. Чем меньше удивляет ваш код содержит, тем легче поддерживать (включая себя, три месяца спустя).
Обратите внимание, что предложение Наконец выполняется, даже если блок TRY или CATH содержит оператор возврата.
Один случай, когда вы можете не предвидеть бросок S1: если нить будет прервана, то исключение будет автоматически переброшено в конце блока уловов в любом случае.
Как говорит Понт, наконец-то
блок указывает на намерение, что этот код должен всегда выполняться, что бы ни случилось. Это яснее, чем все ловить, а потом продолжать.
Нет, вам не нужно его использовать. В этом случае он не требуется. Это выбор для Вас и зависит от ресурсов, которые Вы можете/не можете использовать. Если вам нужно очистить любые ресурсы, которые у вас могут быть, то окончательный блок - это лучший вариант.
Возможно, вы сможете гарантировать, что ваш код не вызовет исключение сегодня, но как быть, когда вы вернетесь к нему через 6 месяцев? Или кто-то другой должен внести изменения?
Использование блока наконец
является признанным образцом, который будет иметь смысл для любого программиста, если ваш код делает что-то особенное и другое, он приведет вас или кого-то еще вверх.
Во втором случае контроль дойдет до S2, только если вы проглотите любое исключение, когда-либо попавшее в ловушку! Try-Catch следует использовать не здесь и там, а осторожно.
Ex:
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
// this.cachedException = ex;
// Must swallow any exception here to let control go further!
// If you're not sure enough [which you and me both are not likely to be] - use finally to execute S2 in any condition
}
// No finally block needed (?)
S2;
S3;
-121--2892377- Я думаю, что это похоже на скобки вокруг содержимого оператора if.
Хотя вы можете утверждать, что
if (x) y;
не подведет, что сказать, что какой-то менее опытный программист не придет позже и не отредактирует его до
if (x) y; z;
Возможно, что окончательно блок не нужен для вашего кода в его нынешнем виде, но это всегда хорошая идея оставить его в случае, если код в блоке catch когда-либо изменится.
if (x)
{
y;
}
всегда выигрывает для меня.
Вы можете убедиться, что ваш код сегодня не выбрасывает исключение, но как насчет того, когда вы вернетесь к нему через 6 месяцев? Или кто-то должен внести изменения?
Использование Наконец
, наконец, находится распознанный шаблон, который имеет смысл для любого программиста, если ваш код делает что-то особенное и другое, это будет путешествие вы или кто-то еще вверх.
Во втором случае Control Control достигнет только S2, если вы проглотите любое исключение, когда-либо попадающее в Catch Block! TRY-CALL не следует использовать здесь - и там, но осторожно.
EX:
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
// this.cachedException = ex;
// Must swallow any exception here to let control go further!
// If you're not sure enough [which you and me both are not likely to be] - use finally to execute S2 in any condition
}
// No finally block needed (?)
S2;
S3;
Наконец-то блок используется для выполнения ресурса очистки, либо исключение происходит или нет, наконец-то блокировка будет называться, так что это идеальное место для работы.
В вашем конкретном случае нет никакой разницы ..
Но если вы не поймать исключение, а некоторые конкретные подкласс Exception, то не было бы разницы. И это, вероятно, нормальный рисунок при рассмотрении блок Try-Catch-Came.