Должен ли я сломаться после броска исключения? - PullRequest
21 голосов
/ 13 июня 2009

Я пишу собственный класс на C # и выкидываю пару исключений, если в некоторых методах люди вводят неверные данные. Если выброшено исключение, будет ли выполняться какой-либо код в методе после броска? Должен ли я ставить перерыв после броска, или бросок всегда выходит из метода?

Ответы [ 6 ]

31 голосов
/ 13 июня 2009

Когда вы выбрасываете исключение, следующий исполняемый код - это любой блок catch, который покрывает этот бросок внутри метода (если есть), тогда finally блок (если есть ). Вы можете попробовать, поймать, попробовать, поймать или попробовать, наконец. Затем, если исключение не обработано, переброшено блоком перехвата или не перехвачено, управление возвращается вызывающей стороне. Например, вы получите «Да1, Да2, Да3» из этого кода ...

try
{
    Console.WriteLine("Yes1");
    throw (new Exception());
    Console.WriteLine("No1");

}
catch
{
    Console.WriteLine("Yes2");
    throw;
    Console.WriteLine("No2");
}
finally
{
    Console.WriteLine("Yes3");
}

Console.WriteLine("No3");
27 голосов
/ 13 июня 2009

Бросок будет перемещаться вверх по стеку, выходя из метода.

4 голосов
/ 13 июня 2009

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

2 голосов
/ 23 марта 2017

Я пришел сюда в поисках ответа на оригинальный пост и почти пропустил очень ценный ответ, опубликованный Эриком Липпертом . Вот его ответ в комментариях:

Разделите это на три вопроса.

(1) Будет ли выполнен какой-либо код в методе после броска?
ДА. Если исключение было внутри try, то будет выполнен код внутри соответствующих блоков catch или finally. Если нет блока try, тогда NO. Элемент управления переходит к ближайшему включающему фильтру finally, catch или (в vb) исключения в стеке.

(2) Должен ли я сделать перерыв после броска?
НЕТ, никогда не делай этого. Конечная точка оператора throw недоступна; бросок обрабатывается компилятором как переход. Оператор, следующий сразу за броском, недоступен и никогда не будет выполнен.

(3) Бросок всегда выходит из метода?
NO. Если бросок находится в попытке, и попытка имеет соответствующий блок catch, тогда блок catch может «съесть» исключение. Только если нет блока catch, исключение делает нелокальный переход к стеку вызовов.

Если у вас есть дополнительные вопросы по этому поводу, я рекомендую прочитать спецификацию C #; все это поведение четко задокументировано.

Наконец, звучит так, как будто вы выкидываете исключения с "головокружением", как, например, в "эй, звонивший с головой", я сказал вам никогда не давать мне эти данные ". Это здорово, потому что это предотвращает ошибки в звонящих. Но если вы сделаете это, вы должны убедиться, что у звонящего есть способ узнать, чего вы ожидаете! Если вызывающий не может выяснить, собираетесь ли вы бросить или нет, основываясь на вашей документации, то вы не сделали исключение без головы, вы сделали неприятное исключение. Подробнее см. http://blogs.msdn.com/ericlippert/archive/2008/09/10/vexing-exceptions.aspx.

1 голос
/ 13 июня 2009

В дополнение к вашему актуальному вопросу: вы можете переосмыслить, используя исключения, чтобы предоставить пользователю информацию для проверки.

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

1 голос
/ 13 июня 2009

Если вы завернули свой код в блок Try ... Catch ... finally, то код в разделе Final всегда будет выполняться. Например:

Try
  ' do some stuff here
  ' Examine user input
  If user input isn't valid
      Throw new exception
Catch
   Throw ' Just re-throws the same exception
Finally
   ' This code will execute, no matter what - exception or not
End Try
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...