Создает ли многоадресный делегат новую ссылку для каждой цепочки? - PullRequest
1 голос
/ 08 апреля 2019

Многоадресный делегат создает новую ссылку для каждой цепочки?или это тип значения (MSDN говорит иначе)?Я не понимаю, пожалуйста, посмотрите на следующий код.

using System;
class TestClass
{
    static void Main()
    {
        Action origin = new Action(() => { Console.WriteLine("1st line"); });
        Action copyFromOrigin;

        copyFromOrigin = origin;
        origin += new Action(() => { Console.WriteLine("2nd line"); });

        copyFromOrigin.Invoke();

        //result is "1st line", why the "2nd line" is missing? 
        //shouldn't the copyFromOrigin is referencing the origin?
        Console.ReadKey();
    }
}

Ответы [ 2 ]

2 голосов
/ 08 апреля 2019

Делегаты являются неизменными ....

При добавлении нового обработчика создается новый делегат .

Под капотом вызывается метод Delegate.Combine

Объединяет списки вызовов двух делегатов.

Возвращает

Новый делегат со списком вызовов, который объединяет списки вызовов a и b в указанном порядке .Возвращает a, если b равно нулю, возвращает b, если a является нулевой ссылкой, и возвращает нулевую ссылку, если a и b являются нулевыми ссылками.

Вы можете увидеть это в действии здесь

Action action = <>c.<>9__0_0 ?? (<>c.<>9__0_0 = new Action(<>c.<>9.<M>b__0_0));
Action action2 = action;
action = (Action)Delegate.Combine(action, <>c.<>9__0_1 ?? (<>c.<>9__0_1 = new Action(<>c.<>9.<M>b__0_1)));
action2();
Console.ReadKey();
1 голос
/ 08 апреля 2019

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

...