Объяснение наследования делегата - PullRequest
1 голос
/ 19 августа 2011

Я понимаю, что действие - это просто предварительно объявленный делегат, который может принимать один параметр определенного типа.поэтому Action<String> представляет метод, который не имеет возврата и принимает единственный строковый параметр.Пока все хорошо.

В моем коде у меня есть этот метод:

public void Send<TMessageType>(Types.MessageBase<TMessageType> message)
        {
            Console.WriteLine("Message Sent");
            List<Delegate> subscriptions;
            if (register.TryGetValue(typeof(TMessageType), out subscriptions))
            {
                foreach (Delegate subscription in subscriptions)
                {
                    Console.WriteLine("Invoking....");
                    subscription.DynamicInvoke(message);
                }
            }
        }

Все делегаты в переменной подписки фактически были созданы как действия.Мой вопрос: почему мой код работает?Почему мне не нужно возвращать моего делегата в действие (это будет Action<TMessageType>), прежде чем я смогу его использовать?конечно, тип делегата по умолчанию не знает, какие параметры ожидать?

Ответы [ 3 ]

1 голос
/ 19 августа 2011

нет, он не знает и не заботится - он берет кучу «объектных» параметров и вызывает ваше действие с ним.Не проверяется во время компиляции, но во время выполнения - подробности см. Здесь

1 голос
/ 19 августа 2011

Вы используете DynamicInvoke, что, как следует из его названия, динамически вызывает делегат.Это на порядок медленнее, чем Invoke, но может автоматически соответствовать типу параметра во время выполнения, а не полагаться на информацию времени компиляции.

1 голос
/ 19 августа 2011

Ну, краткий ответ, потому что ваш вызов DynamicInvoke является вызовом с поздней привязкой и на самом деле не знает, нужен ли ему даже параметр.

MSDN

Динамически вызывает (с поздним связыванием) метод, представленный текущим делегатом.

В качестве примечания:
Учитывая, что вы знаете тип передаваемого в Action, вам, вероятно, следует реорганизовать свой код, чтобы напрямую вызывать действия, и не использовать DynamicInvoke, если вы можете избежать его, поскольку это повлияет на производительность.Если вы не можете избежать этого из-за не показанных ограничений, пусть будет так.

        List<Action<Types.MessageBase<TMessageType>>> subscriptions;
        if (register.TryGetValue(typeof(TMessageType), out subscriptions))
        {
            foreach (var subscription in subscriptions)
            {
                Console.WriteLine("Invoking....");
                subscription(message);
            }
        }

Конечно, я не знаю, что будет связано с рефакторингом вызова TryGetValue.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...