C # Delegado bajo el capó pregunta
-
03-10-2019 - |
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:
- cómo es posible llamar a invocar sin pasar el parámetro requerido por la función estática.
- Cuando está pasando bajo el capó cuando se asigna el valor de retorno de llamada de invocación
- ¿Qué significa Barry por vía indirecta adicional (en su comentario)
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.