C # kennt zwei Begriffe delegate
und event
. Beginnen wir mit dem ersten.
Delegieren
A delegate
ist eine Referenz auf eine Methode. So wie Sie einen Verweis auf eine Instanz erstellen können:
MyClass instance = myFactory.GetInstance();
Sie können einen Delegaten verwenden, um einen Verweis auf eine Methode zu erstellen:
Action myMethod = myFactory.GetInstance;
Nachdem Sie diese Referenz auf eine Methode haben, können Sie die Methode über die Referenz aufrufen:
MyClass instance = myMethod();
Aber warum würdest du? Sie können auch einfach myFactory.GetInstance()
direkt anrufen . In diesem Fall können Sie. Es gibt jedoch viele Fälle, in denen Sie darüber nachdenken müssen, wo der Rest der Anwendung keine Kenntnisse haben myFactory
oder anrufen sollmyFactory.GetInstance()
direkt .
Ein offensichtlichste ist , wenn Sie ersetzen können , wollen myFactory.GetInstance()
in myOfflineFakeFactory.GetInstance()
von einem zentralen Ort (auch bekannt als Factory - Methode Mustern ).
Fabrikmethodenmuster
Wenn Sie also eine TheOtherClass
Klasse haben und diese verwenden müssen myFactory.GetInstance()
, sieht der Code ohne Delegaten folgendermaßen aus (Sie müssen TheOtherClass
den Typ Ihrer Klasse angeben myFactory
):
TheOtherClass toc;
//...
toc.SetFactory(myFactory);
class TheOtherClass
{
public void SetFactory(MyFactory factory)
{
// set here
}
}
Wenn Sie Delegaten verwenden möchten, müssen Sie den Typ meiner Fabrik nicht offenlegen:
TheOtherClass toc;
//...
Action factoryMethod = myFactory.GetInstance;
toc.SetFactoryMethod(factoryMethod);
class TheOtherClass
{
public void SetFactoryMethod(Action factoryMethod)
{
// set here
}
}
Auf diese Weise können Sie einen Delegaten einer anderen Klasse zur Verwendung zuweisen, ohne Ihren Typ für sie verfügbar zu machen. Das einzige, was Sie verfügbar machen, ist die Signatur Ihrer Methode (wie viele Parameter Sie haben und so).
"Unterschrift meiner Methode", wo habe ich das vorher gehört? O ja, Schnittstellen !!! Schnittstellen beschreiben die Signatur einer ganzen Klasse. Stellen Sie sich Delegierte so vor, als würden sie die Signatur nur einer Methode beschreiben!
Ein weiterer großer Unterschied zwischen einer Schnittstelle und einem Delegaten besteht darin, dass Sie beim Schreiben Ihrer Klasse C # nicht sagen müssen, dass diese Methode diesen Delegatentyp implementiert. Bei Schnittstellen müssen Sie sagen "Diese Klasse implementiert diesen Typ einer Schnittstelle".
Ferner kann eine Delegatenreferenz (mit einigen Einschränkungen, siehe unten) mehrere Methoden (aufgerufen) referenzieren MulticastDelegate
) . Dies bedeutet, dass beim Aufrufen des Delegaten mehrere explizit angehängte Methoden ausgeführt werden. Eine Objektreferenz kann immer nur auf ein Objekt verweisen.
Die Einschränkungen für a MulticastDelegate
bestehen darin, dass die Signatur (Methode / Delegat) keinen Rückgabewert ( void
) und die Schlüsselwörter haben sollte out
und ref
nicht in der Signatur verwendet wird. Natürlich können Sie nicht zwei Methoden aufrufen, die eine Nummer zurückgeben, und erwarten, dass sie dieselbe Nummer zurückgeben. Sobald die Signatur übereinstimmt, ist der Delegat automatisch ein MulticastDelegate
.
Veranstaltung
Ereignisse sind nur Eigenschaften (wie get; set; Eigenschaften für Instanzfelder), die das Abonnement für den Delegaten von anderen Objekten verfügbar machen. Diese Eigenschaften unterstützen get; set; jedoch nicht. Stattdessen unterstützen sie add; entfernen;
So können Sie haben:
Action myField;
public event Action MyProperty
{
add { myField += value; }
remove { myField -= value; }
}
Verwendung in der Benutzeroberfläche (WinForms, WPF, UWP usw.)
Jetzt wissen wir also, dass ein Delegat eine Referenz auf eine Methode ist und dass wir ein Ereignis haben können, um die Welt wissen zu lassen, dass sie uns ihre Methoden geben können, auf die von unserem Delegaten verwiesen werden kann, und wir sind dann eine UI-Schaltfläche: wir kann jeden, der daran interessiert ist, ob ich angeklickt wurde, bitten, seine Methode bei uns zu registrieren (über das Ereignis, das wir ausgesetzt haben). Wir können alle Methoden anwenden, die uns gegeben wurden, und sie von unserem Delegierten referenzieren. Und dann warten wir und warten ... bis ein Benutzer kommt und auf diese Schaltfläche klickt, dann haben wir genug Grund, den Delegaten aufzurufen. Und weil der Delegat auf alle uns gegebenen Methoden verweist, werden alle diese Methoden aufgerufen. Wir wissen nicht, was diese Methoden tun, und wir wissen auch nicht, welche Klasse diese Methoden implementiert. Wir kümmern uns nur darum, dass jemand daran interessiert war, dass wir angeklickt werden.
Java
Sprachen wie Java haben keine Delegierten. Sie verwenden stattdessen Schnittstellen. Sie bitten jeden, der daran interessiert ist, dass wir angeklickt werden, eine bestimmte Schnittstelle zu implementieren (mit einer bestimmten Methode, die wir aufrufen können), und geben dann die gesamte Instanz an, die die Schnittstelle implementiert. Wir führen eine Liste aller Objekte, die diese Schnittstelle implementieren, und können ihre "bestimmte Methode, die wir aufrufen können" aufrufen, wenn wir darauf klicken.