为什么异常会从事件处理程序中传播出去?

Mat*_*ley 4 c# events exception-handling exception event-handling

考虑以下程序.它显示的行为(即异常将从事件处理程序传播出来)是一个"好事"?据我所知,它只会是坏事; 意外异常从他们不应该的功能弹出.在我的特殊情况下,它是杀死线程.那么,在某些情况下,这种行为实际上是件好事吗?这是否有理由说从事件处理程序中排除异常是糟糕的设计?

static class Program {
    static void Main()
    {
        Foo foo = new Foo();
        foo.SomeEvent += ThrowException;

        try 
        {
            foo.OnSomeEvent();
        } 
        catch (Exception) 
        {
            // This is printed out
            Console.WriteLine("Exception caught!");
        }
    }

    static void ThrowException(object sender, EventArgs e)
    {
        throw new Exception();
    }
}

// Define other methods and classes here
class Foo 
{
    public event EventHandler SomeEvent;

    public void OnSomeEvent()
    {
        SomeEvent(this, EventArgs.Empty);
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 17

什么是你的首选替代方案 - 默默地吞下这个例外?我完全不喜欢这样.

实际上,事件只是实现观察者模式的一种方式.如果一个监听器抛出一个异常,我绝对希望将该异常抛回给调用者.我能想到的任何其他行为都会有效地将异常视为不重要.异常的全部意义在于,当出现问题时,您会快速而隐含地发现它.你必须明确地处理异常,这样你就不会在没有意识到的情况下以腐败的状态继续你的快乐方式.

您提出了一个有效的观点,即处理异常的责任.从广义上讲,我发现最好假设任何事情都可以随时抛出异常.除了我知道可能发生特定异常并且我可以处理它的特殊情况之外,我通常不会捕获除顶层以外的异常 - 除了可能包装和重新抛出,或记录和重新抛出.

现在你的一个事件处理程序可能真的应该抛出一个异常 - 它们并没有真正遇到错误状态 - 但是如果它是一个完全合理的异常表明存在严重问题会发生什么呢?虽然程序崩溃是丑陋的,但通常比继续其中一些故障,可能破坏持久状态等更好.

从根本上说,我认为CS/SE领域还没有"正确"的错误处理.我甚至不能确定有做的是简单的表达在所有情况下正确的事情的一种优雅的方式......但我希望,目前的情况并不像好得不能再好.

  • 这是 catch(Exception) 为数不多的正确用法之一。理想情况下,您应该在单独的进程中运行用户脚本,这样它就不会干扰您的程序;如果脚本崩溃,你只会得到一个退出代码,比如 -1073741819 或其他什么。 (2认同)
  • 您可能需要考虑在单独的AppDomain中运行用户脚本 - 该域中引发的任何异常都可能触发域卸载. (2认同)