我可以拥有强大的异常安全和事件吗?

Wim*_*nen 5 c# events exception

假设我有一个方法可以更改对象的状态,并触发事件以通知侦听器此状态更改:

public class Example
{
   public int Counter { get; private set; }

   public void IncreaseCounter()
   {
      this.Counter = this.Counter + 1;
      OnCounterChanged(EventArgs.Empty);
   }

   protected virtual void OnCounterChanged(EventArgs args)
   {
      if (CounterChanged != null)
         CounterChanged(this,args);
   }

   public event EventHandler CounterChanged;
}
Run Code Online (Sandbox Code Playgroud)

即使IncreaseCounter成功完成状态更改,事件处理程序也可能抛出异常.所以我们这里没有强大的异常安全性:

强有力的保证:操作已成功完成或抛出异常,使程序状态与操作开始前完全一致.

当您需要举办活动时,是否有可能拥有强大的异常安全性?

Rob*_*son 3

为了防止处理程序中的异常传播到事件生成器,答案是在 try-catch 内部手动调用 MultiCast Delegate(即事件处理程序)中的每个项目

所有处理程序都将被调用,并且异常不会传播。

public EventHandler<EventArgs> SomeEvent;

protected void OnSomeEvent(EventArgs args)
{
    var handler = SomeEvent;
    if (handler != null)
    {
        foreach (EventHandler<EventArgs> item in handler.GetInvocationList())
        {
            try
            {
                item(this, args);
            }
            catch (Exception e)
            {
                // handle / report / ignore exception
            }
        }                
    }
}
Run Code Online (Sandbox Code Playgroud)

剩下的事情就是实现当一个或多个事件接收者抛出而其他事件接收者没有抛出时执行操作的逻辑。catch() 还可以捕获特定异常并回滚任何更改(如果有意义),从而允许事件接收者向事件源发出已发生异常情况的信号。

正如其他人指出的那样,不建议使用异常作为控制流。如果确实是特殊情况,那么一定要使用例外。如果您遇到很多异常,您可能想使用其他方法。