C#中的事件处理程序是否应该引发异常?

Fly*_*179 33 c# events exception

作为一般规则,是否有任何情况下,负责监听事件的方法可以引发异常(或允许抛出)引发事件的类必须处理?

鉴于此类异常会阻止其他侦听器随后被调用,但允许这种情况发生似乎有点"反社会",但另一方面,如果存在异常,它应该怎么办?

Jar*_*Par 21

从事件处理程序中抛出异常在很多方面类似于从IDisposable.Dispose方法(或C++析构函数)抛出异常.这样做会给你的来电者造成严重破坏,因为你没有多少选择.

  1. 忽略异常并让它传播.这打破了他们的合同,通知所有听众一个事件.如果堆栈上方的任何人捕获异常,这是一个非常现实的问题.
  2. 抓住它调用其他处理程序并重新抛出.但是,如果其中一个投掷也会发生什么呢?
  3. 吞下例外.这一般都很糟糕.事件来源应该不知道他们的来电者,因此无法知道他们吞咽了什么.
  4. 因为你敬酒而崩溃了.

在所有这些#4中是最好的选择.但这很少做,也不能指望.

我认为在你的组件中你真的只有几个选择

  • 您正在调用抛出的代码并处于处理异常的最佳位置.如果你无法处理它,那么期望它被其他任何人处理是不合理的.因此崩溃过程并完成它.
  • 不要调用抛出的API

  • 在这种情况下,具有顶级处理程序的@Joe(续)是可能发生的最糟糕的事情.抛入事件处理程序违反了绝大多数事件的合同,并导致其他组件中的假设被破坏.这几乎肯定会导致这些组件中的未来错误和/或异常.这些失败远非原始的真正失败,因此更难以追查.快速失败并大声失败. (8认同)
  • @Joe事件的合同是所有听众都会收到通知.未通知他们违反了该合同.如果单击按钮时我不能依赖我的处理程序实际执行,那么`Button.Click`事件有什么用呢? (5认同)

War*_*mak 5

应该从事件中产生的唯一两种类型的异常是严重的,可能是流程结束的异常,如System.OutOfMemoryExceptionSystem.DllNotFoundException,以及明显编程错误的东西,如System.StackOverflowExceptionSystem.InvalidCastException.捕获和删除这些异常绝不是一个好主意 - 让它们浮动到顶部,让开发人员决定在应用程序级别如何处理它们.

至于其余的......任何常见的或花园式的异常都System.IO.IOException应该在你的事件中处理,你应该有一些机制来将这样的错误条件返回给调用者.

  • @Joe:在许多情况下,事件代表控制反转,引发事件的实体纯粹是为了事件接收者的利益而这样做,并且并不真正关心接收者是否做了任何事情。有用的是一种以这样的方式调用多播委托中的委托的方法:如果其中一个或多个抛出异常,则所有委托都将被调用,但将抛出一个 EventException<T> ,并带有一个Exceptions 属性产生 IEnumerable<KeyvaluePair<EventHandler<T>, Exception>>。太糟糕了,这样的事情没有标准实现。 (2认同)