9.7 Generische Delegates
Generische Delegates erweisen sich als besonders nützlich, wenn mehrere ähnliche Events ausgelöst werden. Ein kleiner Satz generischer Delegates, die sich in der Anzahl und dem Typ der Parameter unterscheiden, reicht oftmals vollkommen aus, um alle Ereignishandler bedienen zu können.
Sehen wir uns den generischen Delegaten EventHandler<TEventArgs> an, der in der Klassenbibliothek zu finden ist:
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e)
where TEventArgs : EventArgs;
Der generische Typparameter TEventArgs akzeptiert in diesem Fall alle Objekte, die auf die Basis EventArgs zurückzuführen sind. Mit dieser Delegatdefinition lassen sich prinzipiell alle Delegaten beschreiben, die als Typvorgabe von Ereignissen dienen. Leider wurden die Generics nicht schon mit .NET 1.0 eingeführt, sondern erst mit .NET 2.0. So müssen wir uns leider mit sehr vielen Delegaten auseinandersetzen, obwohl ein einziger bereits den Anforderungen vollends genügen würde.
9.7.1 Generische Delegates und Constraints
Die Definition eines generischen Delegates erlaubt es uns, eine Bedingung mit where zu formulieren. Wollen Sie beispielsweise den Typparameter T des Delegates MyDelegate auf die Typen begrenzen, die von der Klasse Demo abgeleitet sind und die Schnittstelle IDisposable implementieren, würde die Anweisung wie folgt lauten:
public delegate void MyDelegate<T>(T param) where T : Demo, IDisposable;
9.7.2 Anpassung des Beispiels »GeometricObjects«
Wir wollen aus der Erkenntnis des letzten Abschnitts Nutzen ziehen und im Projekt GeometricObjects eine Änderung vornehmen, indem wir auf alle Delegatdefinitionen verzichten. Damit die Anwendung anschließend fehlerfrei kompiliert wird und wir weiterhin unsere Ereignisse InvalidMeasure, Moving und Moved auslösen können, müssen wir eine Typanpassung bei den Ereignissen, die in der Klasse GeometricObject definiert sind, vornehmen:
public abstract class GeometricObject : IComparable {
// Ereignisse
public event EventHandler<MovingEventArgs> Moving;
public event EventHandler<EventArgs> Moved;
public event EventHandler<InvalidMeasureEventArgs> InvalidMeasure;
[...]
}
Listing 9.14 Änderung der Klasse »GeometricObject«
Das ist bereits alles. Bei der Registrierung des Ereignishandlers zum Testen müssen wir natürlich die Änderung berücksichtigen.
class Program {
static void Main(string[] args) {
Circle kreis = new Circle();
kreis.InvalidMeasure +=
new EventHandler<InvalidMeasureEventArgs>(kreis_InvalidMeasure);
kreis.Radius = -10;
Console.ReadLine();
}
static void kreis_InvalidMeasure(object sender, InvalidMeasureEventArgs e) {
Console.WriteLine("Der Radius von {0} ist falsch.", e.InvalidMeasure);
}
}
Listing 9.15 Testen der Änderung aus Listing 9.14
Natürlich ist es auch möglich, mit
kreis.InvalidMeasure += kreis_InvalidMeasure
den Ereignishandler bekannt zu geben.
Sie finden den Code des Beispiels auf der Buch-DVD unter ..\Beispiele\Kapitel 9\ GeometricObjectsSolution_9.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.