Могу ли я избежать исключений в C #, продолжая выполнение кода?

У меня есть следующий код C #. Всякий раз, когда обнаруживается исключение, скажем, в строке 1, я никогда не могу достичь других строк (2, 3, 4 и т. Д.).

try
{
    line1
    line2
    ...
}
catch (Exception ex)
{
    ...
}

Можно ли в C # сказать, что если строка 1 генерирует исключение, просто перейдите к другим строкам (2, 3, 4 и т. Д.)?

Вы переносите код VB6, который (как и большинство) злоупотребляет On Error Resume Next?
Greg D 13.10.2009 15:51:35
Я понимаю, что это отрицательные результаты, потому что это была бы ужасная, ужасная практика, но я думаю, что за это следует проголосовать. Это не единственный разработчик, который воспитывался в традиции VB6 «On Error Resume Next», и эта информация действительно должна быть доступна всем им. Я полагаю, что я рассматриваю возражение по этому вопросу как возражение за ответ - продвижение лекарства, а не болезни.
Dinah 13.10.2009 16:02:40
@OP, То, что вы пытаетесь сделать, это игнорировать, а не избегать.
Çağdaş Tekin 19.10.2009 01:07:51
13 ОТВЕТОВ
РЕШЕНИЕ

Вы можете создать метод SkipOnError следующим образом:

private SkipOnError(Action action)
{
    try 
    {
        action();
    }
    catch
    {
    }
}

Тогда вы могли бы назвать это так:

try
{ 
    SkipOnError(() => /*line1*/);
    line2;
    line3;
} catch {}

Изменить: это должно упростить пропустить данное исключение:

private SkipOnError(Action action, Type exceptionToSkip)
{
    try 
    {
        action();
    }
    catch (Exception e)
    {
        if (e.GetType() != exceptionToSkip) throw;            
    }
}

ПРИМЕЧАНИЕ: я на самом деле не предлагаю вам делать это - по крайней мере, не на регулярной основе, так как я нахожу это довольно хакерским. Но это как бы демонстрирует некоторые функциональные вещи, которые мы можем теперь делать в C #, ура!

То, что я действительно сделал бы, это: Рефакторинг line1в метод ( Extract Method ). Этот новый метод должен обрабатывать любые предсказуемые исключения (если они могут быть обработаны) и, таким образом, оставлять вызывающего в известном состоянии. Потому что иногда вы действительно хотите сделать line1, кроме, может быть, это нормально, если происходит ошибка ...

10
14.10.2009 06:10:15
Идея неплохая, но, по крайней мере, поймать конкретную ошибку ... пропуск любой ошибки очень опасен и не должен быть сделан.
Meta-Knight 13.10.2009 15:55:03
Как насчет вложенности SkipOnError?
leppie 13.10.2009 16:17:54
.. или предоставьте Action <Exception> в качестве вашего обработчика исключений. Тем не менее, выглядит довольно грязно для меня, хотя :)
cwap 13.10.2009 16:17:59
По сути, это то же самое, что и мой ответ, за исключением того, что вы тоже успели опубликовать код ;-)
philsquared 14.10.2009 08:42:44

Вы можете обернуть только строку 1 в блоке try catch.

2
13.10.2009 14:54:56

просто попробуйте поймать вокруг line1

try
{
    try
    {
        line1
    }
    catch (Exception ex)
    {
       ...
    }

    line2
    ...
}
catch (Exception ex)
{
    ...
}

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

5
13.10.2009 15:55:27
это создаст больше головной боли, чем решит в долгосрочной перспективе.
John Lechowicz 13.10.2009 15:02:22
Я согласен, что это не всегда лучшее решение, но бывают моменты, когда вам нужно продолжать. Например, когда вы создаете заказ и возникает ошибка в процессе создания заказа. Было бы неплохо добавить пробную блокировку вокруг блоков, которые могут быть разбиты. Таким образом, вы все равно можете получить всю информацию для заказа, и вашему клиенту не придется полностью пересоздавать заказ.
Josh Mein 13.10.2009 15:06:26
Что если в следующей строке произойдет сбой - jsut сохранит есть исключения до тех пор, пока код не завершит работу?
Davy 13.10.2009 15:51:45
постер говорит, что он не отвечает «скажем, в строке 1» - на мой взгляд, лучше бы продуманный план обработки исключений.
Davy 13.10.2009 15:53:12
@ Дэви, я согласен с тобой. Я просто говорю, что иногда нужно продолжать обработку. Заказ - лучший пример, который я могу придумать. Чем больше информации вы знаете об их заказе, тем легче узнать, как произошла ошибка, и выработать решение. И, возможно, даже исправит их порядок, чтобы им не пришлось его заново создавать.
Josh Mein 13.10.2009 15:59:06

Исключения не следует игнорировать. :)
Они существуют и выбрасываются по причине: возникла исключительная ситуация, не выполнено определенное условие, и я не могу продолжать работать ...

Исключения можно игнорировать, если вы поместите блок try / catch вокруг каждой строки кода, но я не думаю, что вы действительно хотите это сделать ...

16
13.10.2009 14:55:49
В случаях, скажем, где вы создаете заказ, и есть ошибка в процессе создания заказа. Было бы неплохо добавить пробную блокировку вокруг блоков, которые могут быть разбиты. Таким образом, вы все равно можете получить всю информацию для заказа, и вашему клиенту не придется полностью пересоздавать заказ.
Josh Mein 13.10.2009 15:03:27
Я думаю, что это хороший пример того,
Greg 13.10.2009 15:17:25
И то, что он находится в блоке try catch, не означает, что вы игнорируете проблему. Вы можете зарегистрировать проблему, чтобы ее можно было просмотреть и исправить, но процесс можно продолжить. Да, будут времена, когда все должно остановиться на первом шаге, если это не удастся, но это не всегда так.
Josh Mein 13.10.2009 15:18:00
Конечно, вы можете записать проблему и принять соответствующие меры. Но обработка исключения по умолчанию не означает, что процесс может продолжаться. Вы не уверены, что можете получить информацию, которая вам нужна. Вы не уверены, можете ли вы выполнить операцию, которую вам нужно, и т. Д.
Frederik Gheysels 13.10.2009 15:21:06
@jmein: Как вы думаете, ваши клиенты будут счастливы, когда они получат только половину своего заказа. Или, может быть, они будут, если что-то, что случилось, было промежуточным вычислением.
erikkallen 13.10.2009 16:06:57

Вы всегда можете сделать

try 
{
   line1
}
catch (Exception ex)
{
}
line2
...

Но нет ничего похожего на ключевое слово «retry».

1
13.10.2009 14:55:54
Если вы намерены не использовать исключение, я бы посоветовал вам удалить экс из улова.
James 13.10.2009 15:16:41

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

1
13.10.2009 14:59:06

Если есть код, который вы всегда хотите выполнить, даже если выдается исключение, даже если исключение либо не перехватывается в блоке catch, либо блок catch перебрасывает или выдает новое исключение, оно должно войти в блок «наконец»:

try
{
  do(something);
}
catch (InvalidArgumentException ex)
{
  onlyDealWithOneExceptionType();
}
finally
{
  always.runs(no, matter, what);
}
4
13.10.2009 15:00:21
Стоит отметить, что always.runs () может выдавать само исключение, поэтому код finally, как правило, должен быть «безопасным».
axel_c 13.10.2009 15:38:08
try
{
    line1
    line2
    ...
}
catch (Exception ex)
{
    ...
}
finally
{
    if(line1ErrorOccured)
    {
        line2
        ...
    }
}

не слишком много думая, хотя

0
13.10.2009 16:07:09

Вы можете изолировать каждую строку в блоке try-catch, однако, мне просто кажется, что это просто код. Если вы уверены, что строки после первой строки не генерируют исключения или должны выполняться независимо от исключения и не будут генерировать дополнительные ошибки, вы можете добавить блок finally после первого перехвата. Пример:

try{
  line 1;
}
catch(Exception exc){
  //Error handling logic here
}
finally{
  line 2;
  line 3;
  .
  .
  .
  line n;
}
3
13.10.2009 16:37:51
Это будет делать то же самое, что и мой, за исключением того, что код в блоке finally может вызвать исключение, и вы не справитесь с этим. Не безопасно предполагать, что это не бросило бы исключение.
Josh Mein 13.10.2009 16:07:59
И я определенно не рекомендовал помещать каждую строку в блок try catch. Его следует использовать только тогда, когда вы знаете, что существует вероятность разрыва строки, и знаете, что процесс должен продолжаться, если это произойдет.
Josh Mein 13.10.2009 16:09:39
Я согласен с тем, что небезопасно предполагать, что код в блоке finally не сломается, поэтому подчеркнул, что это является обязательным условием для блока finally. Он отличается от вашего решения в том смысле, что он хорошо масштабируется и его легче поддерживать / читать, вместо того, чтобы вкладывать блок try в блок try в блок try и т. Д. Кроме того, в вашем примере, если внутренний тип исключения не перехвачен, он будет касаться родительских блоков catch и, возможно, пропустит весь объем кода.
John Lechowicz 13.10.2009 16:50:11
Улов получил бы исключение, поэтому это не должно быть проблемой. В любом случае, ваше решение будет полезно, если вы избавляетесь от объектов, которые могли быть использованы в try catch. Таким образом, они будут расположены, даже если будет сгенерировано исключение.
Josh Mein 13.10.2009 17:36:49

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

Вы должны восстановиться после первого исключения, а затем перейти к следующей строке, заключив каждую в оператор try / catch.

1
13.10.2009 15:46:28
Наконец блоки не безобразны; они там для очистки. Предположим, у вас есть исключение во время операции с базой данных в блоке Try. В блоке finally вы должны закрыть соединение и избавиться от объекта соединения.
Cylon Cat 13.10.2009 15:10:00
Вот почему я сказал, что это было некрасиво. Моя точка зрения заключалась в том, что если предположить, что line2 и последующие выполняют ту же работу, что и line1, они не должны входить в предложение finally, иначе это будет уродливо.
Philippe 13.10.2009 17:00:17

Как уже говорили другие, сначала убедитесь, что «игнорирование» исключения - это то, что вы действительно хотите сделать. Если это все еще так, и синтаксические накладные расходы всех try-catch слишком высоки, вы можете обернуть их с помощью idom для выполнения.

У меня нет времени набросать весь код прямо сейчас - но вы должны написать метод, который принимает анонимный делегат и выполняет его с помощью try-catch (может быть, регистрирует любые исключения или фильтрует те, которые являются " Хорошо"). Назовите этот метод что-то вроде tryDo. Затем вы можете написать свой код примерно так:

tryDo( delegate(){ line1; } );
tryDo( delegate(){ line2; } );

Это все еще немного многословно, но тогда вы не хотите делать это слишком простым. Достаточно накладных расходов, чтобы заставить вас задаться вопросом, правильно ли это делать :-)

1
13.10.2009 16:06:14

Если возможно обработать ваше исключение и продолжить, вы должны локализовать свои блоки try / catch.

try
{
  line1;
}
catch (ExpectedException e)
{
  // Handle your exception, prepare data for the next lines
  // Could you have prevented the exception in the first place?
}

try
{
  line2;
  line3;
}
catch (AnotherExpectedException e)
{
  // Maybe this exception you can't continue from. Perhaps log it and throw;
}

Помните, что исключения являются исключительными. Если выдается исключение, что-то должно пойти не так. Вы должны попытаться предотвратить исключения в первую очередь.

0
13.10.2009 16:13:48

Вам понадобятся продолжения reifiable, чтобы сделать это. CLR и C # не поддерживают это и, вероятно, никогда не сделают этого. :(

1
13.10.2009 16:16:19