277 lines
4.7 KiB
Markdown
277 lines
4.7 KiB
Markdown
|
|
# Delegates und Events in C#
|
|||
|
|
|
|||
|
|
## Ziel dieser Einheit
|
|||
|
|
|
|||
|
|
In dieser Einheit lernst du:
|
|||
|
|
|
|||
|
|
- was Delegates sind
|
|||
|
|
- wie Lambda-Ausdrücke in C# funktionieren
|
|||
|
|
- wie Delegates in der Praxis eingesetzt werden
|
|||
|
|
- was Events sind und wie sie funktionieren
|
|||
|
|
- wie mehrere Methoden kombiniert werden können
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. Grundidee: Delegates
|
|||
|
|
|
|||
|
|
Delegates sind Datentypen, die Methoden speichern können.
|
|||
|
|
|
|||
|
|
Man kann sich einen Delegate vorstellen wie:
|
|||
|
|
- eine Variable für Methoden
|
|||
|
|
- eine Referenz auf eine Funktion
|
|||
|
|
|
|||
|
|
Ähnlich zu:
|
|||
|
|
- Functional Interfaces in Java
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Definition eines Delegates
|
|||
|
|
|
|||
|
|
public delegate int Vergleich(int a, int b);
|
|||
|
|
|
|||
|
|
Erläuterung:
|
|||
|
|
|
|||
|
|
- neuer Datentyp: Vergleich
|
|||
|
|
- speichert Methoden mit:
|
|||
|
|
- Rückgabewert: int
|
|||
|
|
- zwei Parametern vom Typ int
|
|||
|
|
|
|||
|
|
Wichtig:
|
|||
|
|
- Signatur muss genau passen
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Verwendung mit Lambda-Ausdruck
|
|||
|
|
|
|||
|
|
Vergleich v = (x, y) =>
|
|||
|
|
{
|
|||
|
|
if (x > y)
|
|||
|
|
return 1;
|
|||
|
|
else if (y > x)
|
|||
|
|
return -1;
|
|||
|
|
else
|
|||
|
|
return 0;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
Erläuterung:
|
|||
|
|
|
|||
|
|
- Lambda-Ausdruck = anonyme Methode
|
|||
|
|
- definiert das Verhalten direkt im Code
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Praxisbeispiel: Sortieren mit Delegate
|
|||
|
|
|
|||
|
|
int[] array = { 9, 1, 8, 2, 7, 3, 6, 4, 5 };
|
|||
|
|
|
|||
|
|
BubbleSort(array, v);
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Methode BubbleSort
|
|||
|
|
|
|||
|
|
public static void BubbleSort(int[] array, Vergleich vergleich)
|
|||
|
|
|
|||
|
|
Erläuterung:
|
|||
|
|
|
|||
|
|
- Delegate bestimmt die Sortierlogik
|
|||
|
|
- flexibel (z.B. aufsteigend / absteigend)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Aufruf des Delegates
|
|||
|
|
|
|||
|
|
if (vergleich(array[j], array[j + 1]) == 1)
|
|||
|
|
|
|||
|
|
- Delegate wird wie eine Methode verwendet
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Tauschen von Werten
|
|||
|
|
|
|||
|
|
(array[j], array[j + 1]) = (array[j + 1], array[j]);
|
|||
|
|
|
|||
|
|
- Tupel-Zuweisung
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. Vordefinierte Delegates
|
|||
|
|
|
|||
|
|
C# bietet bereits fertige Delegates:
|
|||
|
|
|
|||
|
|
Action<int> action;
|
|||
|
|
Func<int, double> func;
|
|||
|
|
Predicate<int> predicate;
|
|||
|
|
Comparison<string> comparison;
|
|||
|
|
|
|||
|
|
Erläuterung:
|
|||
|
|
|
|||
|
|
- Action → keine Rückgabe (void)
|
|||
|
|
- Func → mit Rückgabewert
|
|||
|
|
- Predicate → bool
|
|||
|
|
- Comparison → Vergleich
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. Events – Grundidee
|
|||
|
|
|
|||
|
|
Events werden verwendet, um auf Ereignisse zu reagieren.
|
|||
|
|
|
|||
|
|
Beispiel:
|
|||
|
|
- Button wird geklickt
|
|||
|
|
- Methode wird ausgelöst
|
|||
|
|
|
|||
|
|
Pattern:
|
|||
|
|
- Publisher (sendet Ereignis)
|
|||
|
|
- Subscriber (reagiert darauf)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Die Button-Klasse
|
|||
|
|
|
|||
|
|
internal class Button
|
|||
|
|
{
|
|||
|
|
public event EventHandler? OnClick;
|
|||
|
|
|
|||
|
|
public string Text { get; set; }
|
|||
|
|
|
|||
|
|
public void Click()
|
|||
|
|
{
|
|||
|
|
Console.WriteLine("Es wurde auf den Button geklickt...");
|
|||
|
|
OnClick?.Invoke(this, EventArgs.Empty);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Erläuterung
|
|||
|
|
|
|||
|
|
- event → Event deklarieren
|
|||
|
|
- EventHandler → Delegate
|
|||
|
|
- Invoke() → Event auslösen
|
|||
|
|
|
|||
|
|
Wichtig:
|
|||
|
|
|
|||
|
|
- Null-Prüfung ist notwendig
|
|||
|
|
- sonst NullReferenceException
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. Event abonnieren
|
|||
|
|
|
|||
|
|
Button b = new Button();
|
|||
|
|
b.Text = "Ich bin ein Button";
|
|||
|
|
|
|||
|
|
b.OnClick += ButtonClicked;
|
|||
|
|
b.OnClick += ButtonClicked;
|
|||
|
|
b.OnClick -= ButtonClicked;
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Erläuterung
|
|||
|
|
|
|||
|
|
- += → hinzufügen
|
|||
|
|
- -= → entfernen
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. Lambda als Event-Handler
|
|||
|
|
|
|||
|
|
b.OnClick += (s, e) => Console.WriteLine("Über Lambda-Ausdruck");
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 10. Event auslösen
|
|||
|
|
|
|||
|
|
b.Click();
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 11. Event-Handler-Methode
|
|||
|
|
|
|||
|
|
public static void ButtonClicked(object? sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine((sender as Button)?.Text);
|
|||
|
|
Console.WriteLine("Der Klick wurde verarbeitet...");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Erläuterung
|
|||
|
|
|
|||
|
|
- muss zur Delegate-Signatur passen
|
|||
|
|
- sender enthält die Quelle des Events
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 12. Multicast-Delegates
|
|||
|
|
|
|||
|
|
Action<string> a;
|
|||
|
|
|
|||
|
|
a = Console.WriteLine;
|
|||
|
|
a += (s) => Console.WriteLine(s.ToUpper());
|
|||
|
|
a += (s) => Console.WriteLine(s.Substring(0, s.Length / 2));
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Aufruf
|
|||
|
|
|
|||
|
|
a.Invoke("Hallo, Welt!");
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Erläuterung
|
|||
|
|
|
|||
|
|
- mehrere Methoden werden hintereinander ausgeführt
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 13. Zugriff auf einzelne Methoden
|
|||
|
|
|
|||
|
|
Delegate[] invocationList = a.GetInvocationList();
|
|||
|
|
invocationList[1].DynamicInvoke("Dynamisch aufgerufen");
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 14. Zentrale Konzepte im Überblick
|
|||
|
|
|
|||
|
|
### Delegate
|
|||
|
|
- speichert Methoden
|
|||
|
|
- ermöglicht flexible Programmierung
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Lambda-Ausdruck
|
|||
|
|
- anonyme Funktion
|
|||
|
|
- direkt im Code definiert
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Event
|
|||
|
|
- wendet Delegates an
|
|||
|
|
- reagiert auf Ereignisse
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Multicast
|
|||
|
|
- mehrere Methoden gleichzeitig ausführen
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Zusammenfassung
|
|||
|
|
|
|||
|
|
- Delegates sind Methoden-Referenzen
|
|||
|
|
- Lambda-Ausdrücke definieren Verhalten
|
|||
|
|
- Delegates machen Code flexibel
|
|||
|
|
- Events nutzen Delegates zur Kommunikation
|
|||
|
|
- Multicast erlaubt mehrere Methoden gleichzeitig
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Verständnisfragen
|
|||
|
|
|
|||
|
|
- Was ist ein Delegate?
|
|||
|
|
- Warum müssen Signaturen übereinstimmen?
|
|||
|
|
- Was ist der Unterschied zwischen Action und Func?
|
|||
|
|
- Wie funktioniert ein Event?
|
|||
|
|
- Warum ist die Null-Prüfung bei Events wichtig?
|