Распространение исключений в C # - PullRequest
3 голосов
/ 08 декабря 2010

Предположим, у меня есть три функции doA (), doB () и doC () в программе на C #, где я знаю, что doA () будет вызывать doB (), которая, в свою очередь, вызывает doC ().

Поскольку doC () должен взаимодействовать с базой данных, я знаю, что он вполне может генерировать исключения, которые он не сможет разрешить, которые должны быть доведены до сведения пользователя. На данный момент у меня есть код, который может генерировать ошибку в попытке try / catch в doC (), а затем вызов doC () в doB () в другой try / catch и аналогичным образом вызов doB () в doA () в блоке try / catch. Это позволяет мне просто использовать бросок; выкинуть исключение до doA (), где можно что-то разумно сделать, чтобы отобразить это пользователю.

Хотя это немного похоже на излишество. Мне интересно, если я не планирую иметь дело с исключением в doB () или doC (), могу ли я просто избавиться от блоков try / catch там.

Предполагая, что блоки окончательно не задействованы, какова наилучшая практика для решения подобных ситуаций?

Ответы [ 7 ]

10 голосов
/ 08 декабря 2010

Если ваши блоки улова такие:

catch (Exception)
{
    throw;
}

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

Лично у меня в коде очень мало блоков try / catch - и хотя существует множество неявных блоков try / finally, в основном из-за операторов using.

5 голосов
/ 08 декабря 2010

Вам нужно поймать, только если вы собираетесь что-то сделать (или пытаетесь остановить распространение). Если вы не поймаете, это переходит к улову в звонящем. В вашем случае кажется, что doA () (или, возможно, вызывающая программа, в зависимости от того, где вы можете с ней работать) - единственная функция, которая нуждается в try / catch.

5 голосов
/ 08 декабря 2010

Да, я бы избавился от блоков try / catch - просто позвольте исключению распространиться на верхний уровень, а затем перехватите его там.Поймать исключение только для повторного выброса с throw; просто бесполезно, хотя следующий вариант на самом деле вреден, так как уничтожает информацию трассировки стека:

catch (Exception exception)
{
    throw exception;
}
2 голосов
/ 08 декабря 2010

Исключения заполняют стек вызовов.

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

Чтобы ответить на ваш вопрос: в вашем случае нет необходимости отбрасывать исключение.

0 голосов
/ 08 декабря 2010

Тип исключений, которые вы будете ловить, может отличаться на каждом уровне, я не уверен, что вы делаете на 3 уровнях, но на вершине стека вы можете только один тип исключений, на нижнем уровне Это может быть другой тип исключения, который вынуждает вас использовать более широкий тип исключения, чем определенный, который может не иметь четкой информации.

Так что это зависит от типов исключений, которые вы будете выдавать.

0 голосов
/ 08 декабря 2010

Короче говоря, ответ на ваш вопрос - да. Единственная причина поймать исключение - сделать что-то с ним. Если вы не можете сделать ничего полезного в DoC (), просто дайте ему всплыть.

Хорошей практикой всегда является использование блоков catch в точках входа вашего кода (как правило, в обработчиках событий в приложении win form), чтобы ничто не оставалось без изменений. В этот момент вы можете сказать пользователю.

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

0 голосов
/ 08 декабря 2010

ИМХО, исключение следует отлавливать наименьшее возможное количество раз, на самом деле это довольно дорогая операция для отлова исключения.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...