Если я зарегистрируюсь на событие в c # во время его отправки, гарантировано ли, что меня больше не вызовут во время этой отправки?

StackOverflow https://stackoverflow.com/questions/141423

  •  02-07-2019
  •  | 
  •  

Вопрос

В C # я иногда ловлю себя на том, что хочу зарегистрировать метод для события в середине отправки этого же события.Например, если у меня есть класс, который переключает состояния на основе последовательных отправлений одного и того же события, я мог бы захотеть, чтобы обработчик первого состояния отменил регистрацию сам и зарегистрировал второй обработчик.Однако я не хочу, чтобы второй обработчик отправлялся до следующего запуска события.

Хорошей новостью является то, что, похоже, реализация Microsoft на C # ведет себя именно таким образом.Синтаксический сахар регистрации события заменяется вызовом System.Delegate.Combine, который просто объединяет текущий список вызовов и новый метод в отдельный список и присваивает его свойству event.Это дает мне именно то поведение, которое я хочу.

Итак, мой вопрос заключается в следующем:гарантируется ли такое поведение языковым стандартом?Мне нравится иметь возможность запускать свой код C # на других платформах под управлением mono, и, как правило, я хочу убедиться, что я не делаю предположений о стандарте языка на основе его реализации.

Я не смог найти никакой окончательной информации о 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
Это было полезно?

Решение

Да, это гарантировано.

Из унифицированной спецификации C # 3.0, раздел 15.1:

Однако, когда два ненулевых экземпляра делегата объединяются, их списки вызовов объединяются — в порядке левого операнда, затем правого операнд — для формирования нового списка вызовов, который содержит две или более записей.

Обратите внимание на "новый список вызовов".И снова в разделе 15.3:

После создания экземпляра экземпляры делегата всегда ссылаются на один и тот же целевой объект и метод.Помните, что когда два делегата объединяются или один удаляется из другого, новый делегат выдает свой собственный список вызовов;списки вызовов делегатов объединенные или удаленные остаются неизменными.

Наконец, MSDN для системы.Делегировать состояния:

Делегаты являются неизменяемыми;после создания список вызовов делегата не изменяется.

Я подозреваю, что в спецификации интерфейса что-то есть - я проверю, если хотите, но, надеюсь, эти три придали вам достаточно уверенности :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top