Что проку от наконец блок, которому предшествует всеобъемлющий блок выгоды в C#?

Рассмотрите следующую структуру кода 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.
}
11
задан Daniel Fortunov 11 January 2010 в 12:18
поделиться

9 ответов

Предположение, что S1 не может бросить, является хрупким, учитывая сценарии истощения ресурсов (то есть, у вас нет памяти). Даже если оправдано (большой, если), незначительные изменения в коде могут ввести исключение.

Поскольку S2 обычно обеспокоен уборкой и выделением ценных ресурсов, вкладывая его в наконец-то блокировку, связывает, что намерение четко. Установка такого кода, где это возможно, в Dispose () метод ресурсов, владеющего объектом и замена пункта TRY / Наконец с предложением использования, может сообщить о намерении еще лучше (и более идиоматически для C #).

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

Re Внешний вопрос: S3 должен быть помещен в наконец, если оно касается очистки. Если это предполагает успех блока попробовать, он должен быть размещен после окончательного блока. Если выявление вашего улова не рихроу, я лично интерпретирую это, чтобы означать, что вы преодолели и могли действовать с обычными операциями. Однако все «сохранить исключение, чтобы повторно бросить позже», путает меня. Как правило, я бы посоветовал с сохранением исключения для предшествующих измерений вне метода. Это необычно и кажется запутанным мне. Чем меньше удивляет ваш код содержит, тем легче поддерживать (включая себя, три месяца спустя).

12
ответ дан 3 December 2019 в 01:53
поделиться

Обратите внимание, что предложение Наконец выполняется, даже если блок TRY или CATH содержит оператор возврата.

3
ответ дан 3 December 2019 в 01:53
поделиться

Один случай, когда вы можете не предвидеть бросок S1: если нить будет прервана, то исключение будет автоматически переброшено в конце блока уловов в любом случае.

Как говорит Понт, наконец-то блок указывает на намерение, что этот код должен всегда выполняться, что бы ни случилось. Это яснее, чем все ловить, а потом продолжать.

10
ответ дан 3 December 2019 в 01:53
поделиться

Нет, вам не нужно его использовать. В этом случае он не требуется. Это выбор для Вас и зависит от ресурсов, которые Вы можете/не можете использовать. Если вам нужно очистить любые ресурсы, которые у вас могут быть, то окончательный блок - это лучший вариант.

0
ответ дан 3 December 2019 в 01:53
поделиться

Возможно, вы сможете гарантировать, что ваш код не вызовет исключение сегодня, но как быть, когда вы вернетесь к нему через 6 месяцев? Или кто-то другой должен внести изменения?

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

-121--2892376-

Во втором случае контроль дойдет до 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;
}

всегда выигрывает для меня.

3
ответ дан 3 December 2019 в 01:53
поделиться

Вы можете убедиться, что ваш код сегодня не выбрасывает исключение, но как насчет того, когда вы вернетесь к нему через 6 месяцев? Или кто-то должен внести изменения?

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

1
ответ дан 3 December 2019 в 01:53
поделиться

Во втором случае 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;
1
ответ дан 3 December 2019 в 01:53
поделиться

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

3
ответ дан 3 December 2019 в 01:53
поделиться

В вашем конкретном случае нет никакой разницы ..

Но если вы не поймать исключение, а некоторые конкретные подкласс Exception, то не было бы разницы. И это, вероятно, нормальный рисунок при рассмотрении блок Try-Catch-Came.

2
ответ дан 3 December 2019 в 01:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: