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

时间:2010-06-24 23:06:01

标签: c# events exception

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

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

5 个答案:

答案 0 :(得分:20)

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

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

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

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

答案 1 :(得分:5)

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

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

答案 2 :(得分:1)

在理想的世界中,事件处理程序不应引发异常。在事件处理程序中引发异常往往导致很难处理情况和意外行为。正如您所提到的 - 这会阻止后续事件处理程序查看事件,并且异常会在事件生成时传播到事件生成器的代码中。

理想情况下,事件处理程序应该很快(如果它们长时间运行,它们应该尝试在单独的线程中安排工作)并且尽可能接近无错误。

答案 3 :(得分:1)

理想的说,不应该存在例外。在开发人员真实的单词中,总是会出现异常,并且应该根据情况要求截取(捕获),传播或禁止异常。

所以

  

是否有任何情况   哪种方法可以接受   负责听取一个事件   抛出异常

是。您可以期望每个方法都有异常,对事件负责或不负责。

要从Windows应用程序中捕获几乎所有异常,请使用:
AppDomain.CurrentDomain.UnhandledException
Application.ThreadException

答案 4 :(得分:1)

这里的一些答案表明从事件处理程序抛出(“为你的调用者造成破坏”,“往往会导致非常难以处理的情况和意外的行为”,......)。

恕我直言,这是无稽之谈。

一般的情况下,从事件处理程序抛出是完全可以的。其他事件处理程序当然不会运行 - 抛出的事件处理程序也不会运行到最后,也不会触发事件触发和捕获它之间的任何其他代码。所以呢?抛出异常时不执行代码是完全正常的 - 如果你需要保证它被执行,那么使用finally块。

当然,在任何特定的情况下,您可能需要考虑适合处理的异常(如果有的话),就像使用任何其他代码一样。

与往常一样,没有适用于所有情况的严格规定。其中一个答案是“事件处理程序应该快......并且接近无错误......”。一个反例是ASP.NET Page.Load事件。

.NET中的一般规则是吞下所有异常几乎总是一个坏主意:这适用于事件处理程序,就像它对任何其他代码一样。

所以原始问题的答案“在某种情况下,负责监听事件的方法可以接受抛出异常”非常明确地

正如问题的答案“是否有任何情况下,负责监听事件的方法可以接受异常”也是肯定的。