如果我在调度时在c#中注册了一个事件,是否保证在该调度期间不会再次被调用?

时间:2020-03-06 14:48:09  来源:igfitidea点击:

在C#中,我发现自己偶尔想在该事件的派发过程中为该事件注册一个方法。例如,如果我有一个基于相同事件的连续分派来转换状态的类,则我可能希望第一个状态的处理程序自己注销并注册第二个处理程序。但是,我不希望在下一次事件触发之前分派第二个处理程序。

好消息是,看起来Microsoft的Cbeveves实现正是这种方式。事件注册语法糖被对System.Delegate.Combine的调用所代替,该调用仅将当前调用列表和新方法连接到一个单独的列表中,并将其分配给event属性。这确实给了我想要的行为。

因此,我的问题是:语言标准是否保证了这种行为?我希望能够在mono下的其他平台上运行Ccode,并且通常希望确保我不会基于其实现对语言标准做出假设。

我在MSDN上找不到任何确定的信息。

如果我们想要我正在谈论的特定示例,请参考以下示例:

delegate void TestDelegate();
    static event TestDelegate TestEvent;

    static void Main (string[] args) {
        TestEvent += TestDelegateInstanceFirst;
        TestEvent();
        TestEvent();
    }

    static void TestDelegateInstanceFirst () {
        Console.WriteLine("First");
        TestEvent += TestDelegateInstanceSecond;
    }

    static void TestDelegateInstanceSecond () {
        Console.WriteLine("Second");
    }

至少在Windows上,输出为:

First
First
Second

解决方案

是的,有保证。

根据统一的C3.0规范,第15.1节:

However, when two non-null delegate
  instances are combined, their
  invocation lists are concatenated—in
  the order left operand then right
  operand—to form a new invocation list,
  which contains two or more entries.

注意"新调用列表"。再次在15.3节中:

Once instantiated, delegate instances
  always refer to the same target object
  and method. Remember, when two
  delegates are combined, or one is
  removed from another, a new delegate
  results with its own invocation list;
  the invocation lists of the delegates
  combined or removed remain unchanged.

最后,MSDN for System.Delegate指出:

Delegates are immutable; once created,
  the invocation list of a delegate does
  not change.

我怀疑CLI规范中会检查我们是否想要的东西,但希望这三个给我们足够的信心:)