Rückruffunktionen sind ein wichtiger Bestandteil der Windows-Programmierung. Wenn Sie über einen C- oder C++-Programmierhintergrund verfügen, haben Sie Rückrufe in vielen Windows-APIs verwendet. Nach dem Hinzufügen des Schlüsselworts AddressOf zu VB können Entwickler und Entwickler APIs nutzen, die zuvor eingeschränkt waren. Rückruffunktionen sind eigentlich Zeiger auf Methodenaufrufe, auch Funktionszeiger genannt, die eine sehr leistungsstarke Programmierfunktion darstellen. .NET implementiert das Konzept von Funktionszeigern in Form von Delegaten. Das Besondere an ihnen ist, dass .NET-Delegaten im Gegensatz zu C-Funktionszeigern typsicher sind. Dies zeigt, dass der Funktionszeiger in C nur ein Zeiger auf eine Speichereinheit ist. Wir können nicht sagen, worauf dieser Zeiger tatsächlich zeigt, geschweige denn die Parameter und Rückgabetypen. Wie in diesem Kapitel beschrieben, fungieren .NET-Delegates als typsichere Operation. Im Folgenden erfahren Sie, wie .NET Delegaten zur Implementierung von Ereignissen verwendet.
1. Vertrauen
Wenn Sie eine Methode an eine andere Methode übergeben möchten, müssen Sie einen Delegaten verwenden. Um zu verstehen, was sie bedeuten, werfen Sie einen Blick auf den folgenden Code:
int i = int.Parse("99");
Wir sind es gewohnt, Daten als Parameter an Methoden zu übergeben, wie im obigen Beispiel gezeigt. Die Übergabe einer anderen Methode an eine Methode klingt also etwas seltsam. Manchmal wird die von einer Methode ausgeführte Operation nicht an den Daten, sondern an einer anderen Methode ausgeführt, was komplizierter ist. Wir wissen nicht, was die zweite Methode zur Kompilierzeit ist. Diese Informationen können nur zur Laufzeit abgerufen werden, daher müssen wir die zweite Methode als Parameter an die erste Methode übergeben. Hier sind einige Beispiele: Zur Erklärung :
1. Threads starten ----- In C# können Sie den Computer anweisen, bestimmte neue Ausführungssequenzen parallel auszuführen. Diese Sequenz wird als Thread bezeichnet. Verwenden Sie die Start()-Methode für eine Instanz von akkumuliertem System.Threading.Thread, um die Ausführung eines Threads zu starten. Wenn Sie den Computer anweisen möchten, eine neue Ausführungssequenz zu starten, müssen Sie angeben, wo die Sequenz ausgeführt werden soll. Dem Computer müssen die Details der Methode zur Verfügung gestellt werden, um die Ausführung zu starten, d. h. die Thread.Start()-Methode muss einen Parameter annehmen, der die vom Thread aufzurufende Methode definiert.
2. Allgemeine Bibliotheksklassen ------ Es gibt viele Bibliotheken, die Code zur Ausführung verschiedener Standardaufgaben enthalten. Diese Bibliotheken sind normalerweise in sich geschlossen. Auf diese Weise wissen Sie beim Schreiben der Bibliothek, wie Sie die Aufgabe ausführen. Manchmal enthalten Aufgaben aber auch Unteraufgaben. Nur der Clientcode, der die Bibliothek verwendet, weiß, wie diese Unteraufgaben ausgeführt werden. Schreiben Sie beispielsweise eine Klasse, die ein Array von Objekten aufnimmt und diese in aufsteigender Reihenfolge sortiert. Ein Teil des Sortierprozesses besteht jedoch darin, zwei Objekte im Array wiederzuverwenden und sie zu vergleichen, um zu sehen, welches zuerst kommen sollte. Wenn Sie eine Klasse schreiben, die in der Lage sein muss, beliebige Arrays von Objekten zu sortieren, können Sie dem Computer nicht im Voraus mitteilen, wie die Objekte verglichen werden sollen. Clientcode, der Arrays von Objekten in einer Klasse verarbeitet, muss der Klasse auch mitteilen, wie die zu sortierenden Objekte verglichen werden sollen. Mit anderen Worten: Der Clientcode muss bestimmte Details an die Klasse übergeben, damit dies angemessen ist.
3. Ereignisse ------ Benachrichtigen Sie den Code im Allgemeinen darüber, welche Ereignisse aufgetreten sind. Bei der GUI-Programmierung geht es hauptsächlich um die Verarbeitung von Ereignissen. Wenn ein Ereignis auftritt, muss die Laufzeit wissen, welche Methode ausgeführt werden soll. Dazu muss die Methode, die die Zeit verarbeitet, als Parameter des Delegaten übergeben werden. Diese werden später besprochen.
Zuvor haben wir die Regel festgelegt, dass Methodennamen manchmal als Argumente an andere Methoden übergeben werden. Im Folgenden muss angegeben werden, wie dieser Vorgang abgeschlossen werden kann. Der einfachste Weg besteht darin, den Methodennamen als Parameter zu übergeben. Nehmen Sie beispielsweise im vorherigen Thread-Beispiel an, dass ein neuer Thread gestartet wird und es eine Methode namens EntryPoint() gibt, bei der die Ausführung des Threads beginnt.
void EntryPoint()
{
//tun, was auch immer der neue Thread tun muss
}
Sie können auch den folgenden Code verwenden, um die Ausführung eines neuen Threads zu starten:
Thread NewThread = new Thread();
Thread.Start(EntryPoint); //FALSCH
Tatsächlich ist dies eine sehr einfache Methode, die in einigen Sprachen wie C und C++ verwendet wird (in C und C++ ist der Parameter EntryPoint ein Funktionszeiger).
Dieser direkte Ansatz kann jedoch einige Probleme verursachen, z. B. die Typsicherheit. Bei der objektorientierten Programmierung existieren Methoden selten isoliert. Sie müssen normalerweise einer Klasseninstanz zugeordnet werden, bevor sie aufgerufen werden. Und diese Methode berücksichtigt dieses Problem nicht. Daher lässt das .NET Framework diesen direkten Ansatz syntaktisch nicht zu. Wenn Sie eine Methode übergeben möchten, müssen Sie die Details der Methode in einem neuen Objekttyp, einem Delegaten, kapseln. Delegaten sind nur ein besonderer Objekttyp. Das Besondere ist, dass alle zuvor definierten Objekte Daten enthalten, während Delegaten nur die Details der Methoden enthalten.
-