Подтвердить что ты не робот

Должны ли обработчики событий в С# когда-либо создавать исключения?

Как правило, существуют ли когда-либо какие-либо обстоятельства, при которых это приемлемо для метода, ответственного за прослушивание события, чтобы исключить (или позволить его выбросить), что класс, поднимающий событие, должен обрабатывать?

Учитывая, что такое исключение остановит других слушателей от того, что это событие вызвано впоследствии, кажется, что это немного "антисоциально", чтобы это произошло, но, с другой стороны, если есть исключение, что делать?

4b9b3361

Ответ 1

Выбрасывание исключения из обработчика событий во многом схоже с тем, чтобы исключить исключение из метода IDisposable.Dispose (или деструктора С++). Это создает хаос для вашего вызывающего абонента, потому что вы оставляете их с небольшим вариантом.

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

Из всех этих # 4 это лучший вариант. Но это редко сделано и не может считаться.

Я думаю, что в вашем компоненте у вас действительно есть только несколько вариантов

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

Ответ 2

Только два типа исключений, которые должны выходить из событий, являются серьезными, потенциально завершающими процесс, такими как System.OutOfMemoryException или System.DllNotFoundException, и вещами, которые явно программируют ошибки, такие как System.StackOverflowException или System.InvalidCastException. Захват и исключение этих исключений никогда не является хорошей идеей - пусть они всплывают вверх и позволяют разработчику решать, что делать с ними на уровне приложений.

Что касается остальных... в вашем событии должно быть обработано любое общее или исключение из сада, например System.IO.IOException, и у вас должен быть механизм возврата таких условий ошибки вызывающему.

Ответ 3

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

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

Ответ 4

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

Итак,

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

Да. Вы можете ожидать исключения из каждого метода, ответственного или не связанного с событием.

Чтобы поймать почти все исключения из приложения Windows, используйте:
AppDomain.CurrentDomain.UnhandledException
Application.ThreadException

Ответ 5

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

ИМХО это абсурд.

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

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

Как всегда, нет жестких и быстрых правил, которые применяются при любых обстоятельствах. Один из ответов здесь говорит: "Обработчики событий должны быть быстрыми... и близкими к ошибкам...". Контрпример - это событие ASP.NET Page.Load.

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

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

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