Вопрос

Я делал какую-то копание в делегатную дисперсию после прочтения следующего вопроса в так: Delage.createdelegate () и дженерики: привязка ошибок к целевому методу

Я нашел очень хороший код из Барри Келли вhttps://www.blogger.com/comment.gblogid=8184237816669520763669520763&postid=2109708553230166434.

Вот оно (в форме сахара :-)

using System;

namespace ConsoleApplication4
{
    internal class Base
    {
    }

    internal class Derived : Base
    {
    }

    internal delegate void baseClassDelegate(Base b);

    internal delegate void derivedClassDelegate(Derived d);


    internal class App
    {
        private static void Foo1(Base b)
        {
            Console.WriteLine("Foo 1");
        }

        private static void Foo2(Derived b)
        {
            Console.WriteLine("Foo 2");
        }

        private static T CastDelegate<T>(Delegate src)
            where T : class
        {
            return (T) (object) Delegate.CreateDelegate(
                                    typeof (T),
                                    src.Target,
                                    src.Method,
                                    true); // throw on fail
        }

        private static void Main()
        {
            baseClassDelegate a = Foo1; // works fine

            derivedClassDelegate b = Foo2; // works fine

            b = a.Invoke; // the easy way to assign delegate using variance, adds layer of indirection though

            b(new Derived());

            b = CastDelegate<derivedClassDelegate>(a); // the hard way, avoids indirection

            b(new Derived());
        }
    }
}

Я понимаю все это, кроме этого (что выглядит очень простой) линию.

B = A.invoke; // Простой способ назначить делегата с использованием дисперсии, добавляет слой косвествия, хотя

Кто-нибудь может сказать мне:

  1. Как можно позвонить, не передавая параметра, требуемый статической функцией.
  2. Когда происходит под капотом, когда вы назначаете возвращаемое значение от вызывающего вызова
  3. Что такое Барри подразумевает дополнительное косвествие (в его комментарии)
Это было полезно?

Решение

Он не звонит Invoke (Обратите внимание на отсутствие ()), он использует неявное создание делегата для установки b равный новой derivedClassDelegate экземпляр, который указывает на Invoke метод a. Отказ Дополнительное косвенное управление это то, когда b вызывается, это называет a.Invoke(new Derived()) а не просто a(new Derived()).

Сделать то, что на самом деле происходит более явным:

baseClassDelegate a = Foo1; // works fine 

derivedClassDelegate b = Foo2; // works fine 

b = new derivedClassDelegate(a.Invoke); // the easy way to assign delegate using variance, adds layer of indirection though 

b(new Derived());

b = CastDelegate<derivedClassDelegate>(a); // the hard way, avoids indirection 

b(new Derived());

Первый звонок к b Результаты в цепочке, как это (параметры, удаленные для простоты):

b() -> a.Invoke() -> Foo1()

Второй звонок к b Результаты в этом:

b() -> Foo1()

Однако

Это только необходимо, если вам нужен делегат одной подписи, чтобы вызвать делегат другой (менее ограничительной) подписи. В его примере вы могли бы просто установить b = Foo1 И это будет компилировать, но это не проиллюстрирует точку.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top