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

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

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

33
задан Flynn1179 24 June 2010 в 23:25
поделиться

5 ответов

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

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

Из всех этих вариантов №4 - лучший вариант. Но это редко делается, и на него нельзя рассчитывать.

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

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

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

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

1
ответ дан 27 November 2019 в 19:30
поделиться

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

Итак

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

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

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

1
ответ дан 27 November 2019 в 19:30
поделиться

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

ИМХО это ерунда.

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

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

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

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

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

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

1
ответ дан 27 November 2019 в 19:30
поделиться

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

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

5
ответ дан 27 November 2019 в 19:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: