C # Delegierten unter der Haube Frage
-
03-10-2019 - |
Frage
ich tat einige Gräben um in Delegaten Varianz nach den folgenden Fragen in SO lesen: Delegate.CreateDelegate () und Generika: Fehler zu Zielmethode Bindung
fand ich ein sehr schönes Stück Code von Barry Kelly auf https://www.blogger.com/comment.g?blogID=8184237816669520763&postID= 2109708553230166434
Hier ist es (in einer gezuckerten-up Form: -)
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());
}
}
}
Ich verstehe die ganze es außer diesem (was sehr einfach aussieht) Linie.
b = a.Invoke; // Der einfache Weg zu assign delegieren Varianz, fügt Schicht Indirektionsebene obwohl
Kann mir jemand sagen Sie mir:
- , wie es möglich ist, zu nennen aufrufen, ohne den param durch die statische Funktion erforderlich vorbei.
- Wenn unter der Haube geht, wenn Sie den Rückgabewert zuweisen aus aufrufen invoke
- Was bedeutet Barry durch zusätzliche Indirektion (in seinem Kommentar)
Lösung
Er ist nicht Invoke
Aufruf (man beachte das Fehlen von ()
), er mit impliziten Delegierten Schöpfung Satz b
gleich zu einem neuen derivedClassDelegate
Beispiel, dass Punkte auf die Invoke
Methode von a
. Die zusätzliche Indirektion ist, dass, wenn b
aufgerufen wird, ruft er a.Invoke(new Derived())
nicht nur a(new Derived())
.
zu machen, was eigentlich los ist deutlicher:
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());
Der erste Aufruf von b
Ergebnisse in einer Kette wie folgt aus (Parameter der Einfachheit halber weggelassen):
b() -> a.Invoke() -> Foo1()
Der zweite Aufruf von b
ergibt dies:
b() -> Foo1()
Doch
Dies ist nur erforderlich, wenn Sie einen Vertreter eine Unterschrift benötigen einen Delegierten eines anderen (weniger restriktive) Unterschrift aufzurufen. In seinem Beispiel könnten Sie nur Satz b = Foo1
und es wäre kompilieren, aber das würde nicht den Punkt darstellen.