Events and Delegates

In diesem Blogbeitrag handelt es um das Thema “events and delegates”. Ich habe dieses Thema genommen, weil ich erst vor kurzem gelernt habe, was “events and delegates” genau sind und bedeuten. Ich halte es für wichtig, sie zu kennen, weil man sie in jeder Art Applikation treffen kann.

Events und Delegates sind dazu da, damit die Objekte für sich selber denken können. Man kann nämlich nicht immer kontrollieren, was deine Objekte machen. Manchmal passieren Sachen und die Objekte sind auf sich allein gestellt. Du willst, dass deine Objekte schlau genug sind, auf alles antworten zu können. Dazu sind Events da. Ein Objekt löst ein event aus, andere Objekte abonnieren oder empfangen es und somit arbeiten alle Objekte eigenständig zusammen.

Delegate

Ein Delegat ist ein Typ, der eine Referenz auf eine Methode hat. Das kennen wir unter den Objekten, nur ist es hier mit Methoden. Dabei muss die Methode den gleichen Aufbau haben, wie der Delegat (Return type und Parameter). Das Ganze heisst auch, dass es möglich ist, Methoden als Parameter zu übergeben. Man kann vieles nur mit Delegate machen, dazu gehört auch, dass man Delegate miteinander verketten kann. Sie werden somit nacheinander ausgeführt. Dazu werden die Events gebraucht, denn somit können mehrere Methoden an ein Event verkettet werden.

Delegate werden ähnlich wie abstrakte Methoden deklariert, sie benötigen aber das Schlüsselwort delegate.

<Zugriffsart> delegate <Return-Type> <Delegat-Name>(<Parameter>)

Beispiel: public delegate string ConvertsIntToString(int i);

Einfaches Beispiel:

Wir haben eine Applikation und möchten Delegate benutzen. Die Delegate deklarieren wir in eine andere Klasse, man kann sie aber auch in derselben Klasse deklarieren, wo auch die Main Methode ist.

ConvertsIntToString.cs

In Program.cs schreiben wir nun eine Methode mit den gleichen Return-Type und Parameter.

Program.cs

Es ist dem Delegat egal welche Logik die Methode hat, hauptsache der Return-Type und die Parameter stimmen. So kann jetzt eine Instanz vom Delegat erstellt werden, die auf die Methode HiThere zeigt.

Program.cs

Die Instanz someMethod kann nun wie eine einfache Methode aufgerufen werden. Hier wurde 5 als Argument mitgegeben.

Ausgabe:

Hi there! #500

Events

Ohne Delegate gibt es kein Event. Wenn man die Definition eines EventHandlers anschaut [Go To Definition], sieht man, dass es ein Delegat ist. Events dienen dazu da, Informationen bei eingetretene Benutzer-Eingaben oder Änderungen von Daten an andere Klassen (oder Objekte) zu übermitteln. Die typische Events wären z.B. Button-Klicks oder Änderung von Textfelder. Die Klasse, die das Event auslöst, wird Herausgeber (Publisher) genannt. Die Klasse, die das Event empfängt, wird Abonnent (Subscriber) genannt. Der Herausgeber löst ein event aus, was der Abonnent subscribed / empfängt. Ein Event kann auch mehrere Abonnente haben. Dabei werden die Delegate verkettet und nacheinander aufgerufen. Falls ein Event keine Abonnente hat, wird diese nicht ausgelöst. Man kann sich von einem Event anmelden und abmelden. Die Anmeldung geschieht über den +=  Operator und die Abmeldung über den -= Operator. Man kennt diese Operatoren, wenn man z.B. ein Resultat mit 2 addieren möchte (result += 2). Während ein Event mehrere Abonnente haben kann, kann ein Abonnent auch mehrere Events von verschiedene Herausgeber behandeln. 

Der Herausgeber hat typischerweise die Kontrolle, wann ein Event ausgelöst wird, während die Abonnenten kontrollieren, was auf einem Event passieren soll (durch die Event-Methoden). Durch die Klasse EventArgs können Informationen Übergeben werden, die die Event-Methoden möglicherweise brauchen. So eine Klasse kann man selber erstellen, dabei muss es EventArgs vererben.

Events werden mit den Delegattyp deklariert, sie benötigen das Schlüsselwort event und werden nicht instanziiert (nicht mit new).

<Zugriffsart> event <Delegattyp> <Name>;

Beispiel: public event EventHandler<BallEventArgs> BallInPlay;

Einfaches Beispiel:

Ich habe schnell eine kleine Konsolen-Applikation gebaut, in der es eine Person, ein Tier und ein Event PersonSaysSomething gibt. Die Klasse Person ist der Herausgeber, die Klasse Animal ist der Abonnent und Program.cs definiert die properties von PersonEventArgs und löst den Event aus.

PersonEventArgs.cs

Als Properties habe ich den Namen der Person und das Alter genommen. Das sind die Informationen, die mitgegeben werden.

Person.cs

Hier habe ich den Delegat deklariert und ein Event auch. Das Event hat die Signatur des Delegates und als TEventArgs PersonEventArgs. Dazu habe ich die Methode geschrieben, die den Event auslöst mit einer message und eine Referenz zur PersonEventArgs Objekt.

Animal.cs

Im Konstruktor von Animal habe ich eine Referenz zur Person Objekt als Parameter gegeben und mich im Event angemeldet (+=). Die Event-Methode Owner_PersonSaysSomething macht mit den Informationen was sie will.

Program.cs

Hier habe ich alle Objekte instanziiert und den Event ausgelöst.

Ausgabe: 

I’m your owner Tom, I’m 20 years old and I say Hello