考虑以下计划。它显示的行为(即异常将从事件处理程序传播出来)是一个“好事”?据我所知,它只会是坏事;意外异常从他们不应该的功能弹出。在我的特殊情况下,它是杀死线程。那么,在某些情况下,这种行为实际上是件好事吗?这是否有理由说从事件处理程序中排除异常是一种糟糕的设计?
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);
}
}
答案 0 :(得分:16)
您最喜欢的选择是什么 - 默默地吞下这个例外?我根本不喜欢这样。
事件只是一种实现观察者模式的方式。如果一个监听器抛出一个异常,我绝对希望将该异常抛回给调用者。我能想到的任何其他行为都会有效地将异常视为不重要。异常的全部意义在于,当出现问题时,您会快速而隐含地发现它。你必须显式地处理异常,这样你就不会在没有意识到的情况下以腐败的状态继续你的快乐方式。
您提出了一个有效的观点,即处理异常的责任。从广义上讲,我发现最好假设任何事情都可以随时抛出异常。除了我知道可能发生特定异常的特殊情况并且我可以处理它之外,我通常不会捕获除顶级以外的异常 - 除了可能包装和重新抛出,或记录和重新抛出
现在你的一个事件处理程序真的可能不会抛出异常 - 他们没有真正遇到错误 - 但是如果它是一个完全合理的异常会发生什么这表明一个严重的问题?虽然程序崩溃是丑陋的,但通常比继续其中一些故障更好,可能会破坏持久状态等。
从根本上说,我认为CS / SE领域还没有“正确”处理错误。我甚至不确定是否是一种做正确事情的优雅方式,在所有情况下都很容易表达......但我希望目前的情况不如它得到的那么好
答案 1 :(得分:2)
此处讨论的异常处理的主要方面是:如果您不知道如何处理它,请不要捕获异常。但是让我们来谈谈观察者模式,其中通知者发出关于它的状态变化的事件(或信号),并且听众处理它。通知程序的一个很好的例子是发出“点击”事件的按钮。按钮是否关心谁是听众以及他们做了什么?并不是的。如果你是一个倾听者并且你有这个活动,那么你就有工作要做。如果你不能这样做,你必须处理这个错误或通知用户,因为将异常传递给按钮是没有意义的 - 按钮肯定不知道如何处理监听器作业的错误。按钮状态转换器(可能是一些消息循环)也没有 - 您的应用程序最终会在Main()中崩溃。
这就是观察者模式的工作原理 - 事件发射器不知道他们的听众在做什么,并且他们很少有机会正确处理这个异常。
另外请记住,如果异常处理程序抛出异常,可能会有其他侦听器无法接收通知,并且可能导致未定义的应用程序状态。
所以我的建议是在事件处理程序中捕获所有异常,但要弄清楚如何在那里处理它们。否则没人会。
答案 2 :(得分:1)
我个人的偏见是,不捕捉异常通常是件坏事。对我来说,这个规则的唯一“例外”是简单的应用程序,其中未被捕获的异常终止该过程,您会看到错误并修复它。
对于多线程应用程序,如果未捕获的异常的默认行为是zap线程,那么在我看来不要捕获异常是荒谬的。因此,事件处理程序不应该只是将异常放在堆栈中并希望最好。
勉强吞咽异常通常也是不好的,有些不好的东西需要修复。那么也许记录一条消息,然后返回?
答案 3 :(得分:0)
您需要与事件源签订合同,以确定事件处理程序是否可以抛出异常。例如,如果COM对象是事件源,则严格禁止 - 异常不应跨越COM边界。
答案 4 :(得分:0)
事件只不过是函数调用的语法糖,所以它会传播到引发事件的函数。否则,行为应该是什么?例外必须去某个地方。
答案 5 :(得分:0)
最好将异常视为与事件监听器签订合同的一部分。
这意味着,如果监听器很好并且捕获了它的异常(它可以为已知的异常做到这一点),那么你就可以了。
对于其余的,未知的异常,或者在Java语音“运行时异常”中,您需要为它们做好准备,就像它们在代码中出现一样。
我想说的是,如果您正在与事件监听器建立合同,则不能强制它们只抛出一种异常类型(以便您可以使用它们),并且您需要认真对待所有异常。毕竟,它们是“错误状态”的迹象,你不想为消费者隐瞒。