#c# #exception
Вопрос:
Мне интересно, будет ли этот код работать таким образом, что после 10 попыток CleanUp()
будет вызван? Или throw new Exception()
последний блок catch не будет пойман последним блоком catch?
public void Process()
{
try
{}
catch (MyException e)
{
int retries = GetRetries();
if(retries > 10)
{
_logger.LogError("Retried event already {retries} times. Giving up.", retries);
throw new Exception("Giving up!");
}
Process();
}
catch (Exception e)
{
CleanUp();
}
}
Комментарии:
1. Если вы хотите знать, что происходит при запуске кода, запустите код и посмотрите, что произойдет. Почему вы спрашиваете нас, что делает ваш код, когда вы его запускаете?
2. Не используйте исключения для обычного потока управления
3. Потому что код намного сложнее этого, и для создания фактического условия потребуется некоторое усилие. Поэтому я попытался упростить это настолько, насколько мог. И, надеюсь, общий вопрос ясен.
4. @silent Я думаю, вам не нужен ваш сложный код, чтобы проверить это — попробуйте
5. Если вы хотите повторить
Process
попытку, вам нужно иметь цикл, содержащий попытку вокругProcess
с уловом, который будет выдан, как только вы достигнете порога повторной попытки. И затем вы можете попробовать поймать все это дляCleanuUp
(или, наконец, если это имеет больше смысла). Пустоеtry
значение бессмысленно, если вы просто не показываете код в своемtry
для краткости.
Ответ №1:
Нет, это так не работает. Для любого заданного try
/ catch
блока try
соответствующими блоками может быть перехвачено только исключение, возникающее в catch
. Исключения, создаваемые внутри catch
блоков, не могут быть обнаружены другими catch
блоками на том же уровне.
finally
блоки позволяют запускать код, когда элемент управления покидает try
/ catch
по какой-либо причине. Итак, если в конце вашего try
уже есть a CleanUp
, тогда вы просто измените свой final catch(Exception e)
на finally
и удалите CleanUp
в конце try
части.
Однако, если вы хотите запускаться только CleanUp
тогда, когда управление покидает try
/ catch
через исключение, вам не так повезло. В IL есть fault
предложение, которое есть finally
, но только для исключений, но это не представлено в C #.
Поэтому, если вам это нужно, обычно лучше ввести дополнительный bool
, который указывает, что вы достигли конца try
блока без исключения, и используйте это, чтобы сделать ваш CleanUp
вызов условным в finally
.
Или вы можете имитировать try
/ catch
/ fault
путем вложения try
/ catch
блоков:
try
{
try
{}
catch (MyException e)
{
int retries = GetRetries();
if(retries > 10)
{
_logger.LogError("Retried event already {retries} times. Giving up.", retries);
throw new Exception("Giving up!");
}
Process();
}
}
catch
{
//Act as fault
CleanUp();
throw;
}
Комментарии:
1. спасибо, это именно то, что я пытался прояснить.
2. Как написано, этот код ровно ничего не сделает, потому что это внутреннее
try
пустое и поэтому не выдает, поэтому внутреннееcatch
никогда не будет выполняться, и, следовательно, никаких исключений не будет происходить во внешнемtry
, и внешнееcatch
также не будет выполняться. Я подозреваю, что OP действительно хочетtry
обойтиProcess
, если это означает повторную попытку кода.3. @juharr — да, я воспринял это как «содержимое
try
опущенного для краткости». Пустыеtry
блоки бессмысленны.