Причина в том, что когда компилятор видит оператор +=
с делегатом, он использует метод Delegate.Combine
для объединения списков вызовов делегатов, и это возвращает новый делегат.
Вы можете проверить это, если вы вызываете Console.WriteLine(action.GetHashCode());
до и после +=
оператора
Таким образом, вы на самом деле пытаетесь изменить переменную из external scope, присваивая новое значение переменнойв inner scope (переменная в методе).
Объяснение:
Когда мы передаем делегату Action
в качестве параметра, он создает переменную в методе и помещает ссылкуэтому делегату в это.Позже, когда мы вызываем оператор +=
, он возвращает новую ссылку и присваивает ее той же переменной области действия метода.В этот момент он указывает на другой объект , в то время как исходная переменная _action
все еще указывает на исходный объект.
Если вы хотите присвоить новое значение для переменной, созданной вне области действия методаи чтобы изменить его указатель, вы можете передать его по ссылке, используя ключевое слово ref
.Это будет указывать компилятору, что аргумент передается по ссылке, а не по значению:
private static void Subscribe(ref Action action)
{
action += () => { Console.WriteLine("2"); };
}