Примечание: я редактировал этот вопрос, чтобы другим людям с такой же проблемой было легче получить помощь здесь. Чтобы увидеть оригинальный вопрос, который лучше подходит для некоторых ответов, проверьте историю изменений.
В проекте у меня есть класс ExecutionManager, который может содержать несколько экземпляров ExecutionSlot. Класс ExecutionSlot имеет несколько открытых полей событий, таких как:
public event EventHandlers.ObjectEventHandler<IPlugin> ExecuteCompleted;
Для каждого из этих событий в ExecutionManager есть соответствующее событие. Желаемое поведение заключается в том, что каждый раз, когда на ExecutionSlot возникает событие, соответствующее событие также вызывается на содержащем ExecutionManager.
Внедренное решение состояло в том, что всякий раз, когда в ExecutionManager был добавлен слот ExecutionSanager, ExectionManager добавлял свои собственные события в слот ExecutionSlot следующим образом:
executionSlot.ExecuteCompleted += ExecuteCompleted;
Нет необходимости удалять слот ExecutionSlot, поэтому события также никогда не удаляются.
Проблема в том, что событие в ExecutionManager не вызывается. После подтверждения того, что событие выполнялось слотом ExecutionSlot, я обнаружил, что изменение вышеуказанной строки на следующее решило проблему:
executionSlot.ExecuteCompleted += (sender, eventArgs) => ExecuteCompleted(sender, eventArgs);
И я не мог понять, почему, поэтому мой вопрос заключался в том, в чем разница.
Причиной такого различия было то, что первый добавляет текущих слушателей события ExecutionManager к событию ExecutionSlot. Поэтому любые слушатели, добавленные позже, не будут вызываться при возникновении события.
Напротив, последнее решение использует лямбду для вызова события ExecutionManager, что означает, что будут вызываться прослушиватели во время события.
Основная причина неудачного первого решения заключается в том, что делегаты являются неизменяемыми. Поэтому, когда вы добавляете нового делегата в событие, вы фактически создаете новый делегат, который содержит существующие делегаты и добавленные. Поэтому любая ссылка на делегатов, сделанная ранее, не будет содержать вновь добавленного делегата.