Question

Je faisais des fouilles autour de la variance en délégué après avoir lu la question suivante SO: Delegate.CreateDelegate () et génériques: erreur de liaison à la méthode cible

J'ai trouvé un peu très agréable code de Barry à kelly https://www.blogger.com/comment.g?blogID=8184237816669520763&postID= 2109708553230166434

Ici, il est (sous une forme sugared-up: -)

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());
        }
    }
}

Je comprends tout cela, sauf celui-ci (ce qui semble très simple) ligne.

b = a.Invoke; // la manière facile de déléguer assign en utilisant la variance, ajoute la couche d'indirection si

Quelqu'un peut-il me dire:

  1. comment il est possible d'appeler Invoke sans passer le nécessaire par la param fonction statique.
  2. Quand se passe sous le capot lorsque vous attribuez la valeur de retour d'appeler Invoke
  3. Qu'est-ce que signifie Barry par indirection (dans son commentaire)
Était-ce utile?

La solution

Il ne demande pas Invoke (notez l'absence de ()), il utilise la création de délégué implicite à b égal à une nouvelle instance de derivedClassDelegate qui pointe vers la méthode Invoke de a. Le indirection supplémentaire est que lorsque b est appelé, il appelle a.Invoke(new Derived()) plutôt que a(new Derived()).

Pour rendre plus explicite ce qui se passe réellement:

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());

Le premier appel aux résultats de b dans une chaîne comme celui-ci (paramètres éliminés pour simplifier):

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

Le deuxième appel aux résultats de b en ceci:

b() -> Foo1()

Cependant

Ceci est nécessaire que si vous avez besoin d'un délégué d'une signature d'invoquer un délégué d'une autre signature (moins restrictive). Dans son exemple, vous pouvez simplement b = Foo1 ensemble et il serait compiler, mais ce ne serait pas illustrer le point.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top