Должны ли обработчики событий в C # вызывать исключения? - PullRequest
31 голосов
/ 25 июня 2010

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

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

Ответы [ 5 ]

20 голосов
/ 25 июня 2010

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

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

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

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

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

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

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

1 голос
/ 25 июня 2010

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

ИМХО, это чепуха.

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

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

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

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

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

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

1 голос
/ 25 июня 2010

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

Итак,

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

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

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

1 голос
/ 25 июня 2010

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

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

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