C # delegato sotto il cofano domanda
-
03-10-2019 - |
Domanda
I stava facendo un po 'di scavare intorno in varianza delegato dopo aver letto la seguente domanda in SO: Delegate.CreateDelegate () e generici: errore di legame al metodo di destinazione
Ho trovato un bel po 'di codice da Barry Kelly https://www.blogger.com/comment.g?blogID=8184237816669520763&postID= 2109708553230166434
Qui è (in una forma zuccherato-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());
}
}
}
ho capito tutto questo tranne questo (quello che sembra molto semplice) la linea.
b = a.Invoke; // il modo più semplice per assegnare delegato utilizzando varianza, aggiunge livello di riferimento indiretto se
Qualcuno può dirmi:
- come sia possibile chiamare invocare senza passare il parametro richiesto dalla funzione statica.
- Quando sta succedendo sotto il cofano quando si assegna il valore restituito dalla chiamata invoke
- Cosa Barry dire con indirezione extra (nel suo commento)
Soluzione
Non sta chiamando Invoke
(notare la mancanza di ()
), sta usando la creazione delegato implicito a b
posta uguale a una nuova istanza derivedClassDelegate
che indica il metodo di Invoke
a
. L'indirezione aggiuntiva è che quando b
viene invocato, chiama a.Invoke(new Derived())
piuttosto che solo a(new Derived())
.
Per fare quello che succede più esplicito:
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 prima chiamata a risultati b
in una catena come questo (parametri eliminati per semplicità):
b() -> a.Invoke() -> Foo1()
La seconda chiamata ai risultati b
in questo:
b() -> Foo1()
Tuttavia
Questa è necessaria solo se avete bisogno di un delegato di una firma per invocare un delegato di un'altra firma (meno restrittiva). Nel suo esempio, si può solo set b = Foo1
e sarebbe compilare, ma che non sarebbe illustrare il punto.