我可以依赖于按注册顺序调用的事件处理程序吗

本文关键字:事件处理 程序 顺序调用 依赖于 注册 我可以 | 更新日期: 2023-09-27 18:22:19

在当前版本的.NET框架中,在正常情况下(即,在没有有意修改调用列表的情况下),事件的处理程序是否总是按注册顺序调用?这将与多播委托的记录行为一致,多播委托用于实现事件。

这个问题的公认答案是,按照处理程序的注册顺序调用处理程序是一个实现细节,在未来的框架版本中可能会发生变化。我相信微软不太可能做出这样的改变,因此我的问题仅限于当前版本的.NET框架。对同一答案的评论说,可以注册处理程序,使它们在注册顺序中不被调用。如果这是真的,那么请演示导致这种无序执行的代码。请不要包含有意修改调用列表的代码。我在这里关注的是,我是否可以依赖于事件处理程序调用,该调用在所有当前版本的.NET框架中以与注册相同的顺序发生。

我可以依赖于按注册顺序调用的事件处理程序吗

您不能确定事件将始终按特定顺序执行。事件的定义总是可以做它想做的任何事情,并且该事件的实现不是公共API的一部分。

默认情况下,事件将使用单个多播委托作为事件的后备存储,但使用自己的实现非常简单。除了查看源代码之外,没有办法判断事件是否具有自定义实现。

实现事件不具有所述顺序的一种方法是:

public class Foo
{
    private Stack<Action> stack = new Stack<Action>();
    public event Action MyEvent
    {
        add
        {
            stack.Push(value);
        }
        remove { throw new NotImplementedException(); }
    }
    internal void OnMyEvent()
    {
        foreach (var action in stack)
            action();
    }
}

虽然框架类中的大多数事件不会使用这样的定义;大多数人会使用多播委托,了解的唯一方法是查看源代码;例如,从文档中看不出一个事件是这样实现的还是这样实现的:

public class Foo2
{
    public event Action MyEvent;
}

这取决于事件的实现方式。

普通(类似的字段)事件将其所有处理程序存储在单个多播委托中
多播委托按插入顺序调用其处理程序。

其他事件可以自由地以其他顺序存储其处理程序。然而,大多数非标准实现仍然使用隐藏的多播委托,以各种方式存储(例如,EventHandlerList