Pregunta

Me estaba haciendo algo de investigación en torno a la varianza delegado después de leer la siguiente pregunta en SO: Delegate.CreateDelegate () y los genéricos: Error de unión a método de destino

He encontrado un muy buen trozo de código de Barry Kelly en https://www.blogger.com/comment.g?blogID=8184237816669520763&postID= 2109708553230166434

Aquí es (en una forma azucarada en marcha: -)

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

Yo entiendo que todos excepto éste (lo que parece muy simple) de la línea.

b = a.Invoke; // la manera fácil de delegado de asignación utilizando la varianza, añade capa de direccionamiento indirecto, aunque

Puede alguien decirme:

  1. cómo es posible llamar a invocar sin pasar el parámetro requerido por la función estática.
  2. Cuando está pasando bajo el capó cuando se asigna el valor de retorno de llamada de invocación
  3. ¿Qué significa Barry por vía indirecta adicional (en su comentario)
¿Fue útil?

Solución

No está llamando Invoke (nota la falta de ()), que está usando creación delegado implícita al conjunto b igual a una nueva instancia derivedClassDelegate que apunta al método de Invoke a. El direccionamiento indirecto adicional es que cuando se invoca b, llama a.Invoke(new Derived()) en lugar de sólo a(new Derived()).

Para hacer lo que está sucediendo realmente más explícito:

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

La primera llamada a resultados b en una cadena como esta (parámetros eliminadas por motivos de simplicidad):

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

La segunda llamada a resultados b en esto:

b() -> Foo1()

Sin embargo

Esto sólo es necesario si necesita un delegado de una firma para invocar un delegado de otra firma (menos restrictivo). En su ejemplo, usted podría conjunto b = Foo1 y sería compilar, pero eso no sería ilustrar este punto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top