Как (повторно) используются исходные экземпляры при цепочке делегатов .NET?

Скажем, у меня есть следующий код С#:

Action a = TestMethod;
Action b = TestMethod;
Action c = b;
b += a;

Тесты показывают, что b — это не тот же экземпляр, что и c, поэтому очевидно, что оператор + создает новый экземпляр делегата. Это правильное предположение? Использует ли он экземпляр b внутри себя или просто копирует информацию о методе/цели в новый экземпляр?

Кажется, я не могу найти реализацию оператора + для делегатов, класс Delegate, похоже, не содержит его.

Кто-нибудь может пролить свет на этот вопрос?

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

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


person Lasse V. Karlsen    schedule 12.03.2009    source источник


Ответы (2)


Как говорит Кент, += использует для Delegate.Combine, и -= использует Delegate.Remove. См. мою статью о событиях/делегатах для получения дополнительной информации.

Важно то, что делегаты неизменяемы — вызов Combine/Remove вообще не меняет делегата, для которого вы его вызываете, — поэтому вам не нужно ничего клонировать. То же самое верно для всего, что вы делаете с делегатом: если вы получите список вызовов и измените содержимое возвращаемого массива, например, это не изменит того, что на самом деле делает делегат.

(Это похоже на поведение String, если вы хотите думать об этом по-другому.)

person Jon Skeet    schedule 12.03.2009
comment
Спасибо, это все упрощает. - person Lasse V. Karlsen; 12.03.2009

+= эквивалентно Delegate.Combine(). -= эквивалентно Delegate.Remove(). Каждый создает новый экземпляр Delegate и возвращает его.

person Kent Boogaart    schedule 12.03.2009