C # sous la question délégué du capot
-
03-10-2019 - |
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:
- comment il est possible d'appeler Invoke sans passer le nécessaire par la param fonction statique.
- Quand se passe sous le capot lorsque vous attribuez la valeur de retour d'appeler Invoke
- Qu'est-ce que signifie Barry par indirection (dans son commentaire)
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.