Если я зарегистрируюсь на событие в c # во время его отправки, гарантировано ли, что меня больше не вызовут во время этой отправки?
Вопрос
В 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 для системы.Делегировать состояния:
Делегаты являются неизменяемыми;после создания список вызовов делегата не изменяется.
Я подозреваю, что в спецификации интерфейса что-то есть - я проверю, если хотите, но, надеюсь, эти три придали вам достаточно уверенности :)