96 lines
4.0 KiB
C#
96 lines
4.0 KiB
C#
|
|
using System;
|
||
|
|
|
||
|
|
namespace _15_Delegates;
|
||
|
|
|
||
|
|
// C# hat für Lambda-Ausdrücke und Methodenreferenzen ein eigenes Konzept: Die Delegates.
|
||
|
|
// Das Prinzip dahinter ist ähnlich den "functional Interfaces".
|
||
|
|
|
||
|
|
public delegate int Vergleich(int a, int b); // Hier erstellen wir einen neuen Datentypen 'Vergleich', welcher nun int-Methoden mit zwei int-Parametern annehmen kann. Einer Variable dieses Datentyps können wir alle Methoden zuweisen, deren Methodensignatur zum Delegaten passt. Für die Signatur ist wichtig: Rückgabetyp und Parametertypen und -anzahl.
|
||
|
|
|
||
|
|
|
||
|
|
internal class Delegates
|
||
|
|
{
|
||
|
|
public static void Main(string[] args)
|
||
|
|
{
|
||
|
|
// Mit dem Delegate-Datentypen erzeugen wir eine Variable, der wir einen Lambda-Ausdruck zuweisen.
|
||
|
|
// Der Lambda-Ausdruck ist hier eine anonyme Methode, die festlegt, wie die Sortierreihenfolge eines Sortieralgorithmus sein soll.
|
||
|
|
// Siehe: CompareTo()-Methode
|
||
|
|
Vergleich v = (x, y) =>
|
||
|
|
{
|
||
|
|
if (x > y)
|
||
|
|
return 1;
|
||
|
|
else if (y > x)
|
||
|
|
return -1;
|
||
|
|
else
|
||
|
|
return 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
int[] array = { 9, 1, 8, 2, 7, 3, 6, 4, 5 };
|
||
|
|
|
||
|
|
BubbleSort(array, v);
|
||
|
|
Console.WriteLine(String.Join(", ", array));
|
||
|
|
|
||
|
|
// Vordefinierte Delegates in C# sind unter anderem:
|
||
|
|
Action<int> action; // Void-Methode mit bis zu 16 Parametern. (Vergleich zum Consumer in Java)
|
||
|
|
Func<int, double> func; // Methode mit beliebigem Return-Typ und bis zu 16 Parametern. (Vergleich zum Function-Interface in Java)
|
||
|
|
Predicate<int> predicate; // Boolean-Methode mit einem Parameter. (Wie Predicate in Java)
|
||
|
|
Comparison<string> comparison; // Integer-Methode mit zwei Parametern vom selben Typ. (Wie Comparator in Java)
|
||
|
|
|
||
|
|
EventHandler eventHandler; // Wird für Events verwendet (Observer Pattern).
|
||
|
|
|
||
|
|
// Beispiel für Events:
|
||
|
|
Button b = new Button();
|
||
|
|
b.Text = "Ich bin ein Button";
|
||
|
|
|
||
|
|
b.OnClick += ButtonClicked; // Das Event wird durch += abonniert. Hier wird dem Delegaten die Referenz auf die ButtonClicked()-Methode zugewiesen.
|
||
|
|
b.OnClick += ButtonClicked;
|
||
|
|
b.OnClick -= ButtonClicked; // Mit -= können Events wieder de-abonniert werden.
|
||
|
|
b.OnClick += (s, e) => Console.WriteLine("Über Lambda-Ausdruck");
|
||
|
|
|
||
|
|
b.Click(); // Auf den Button klicken...
|
||
|
|
|
||
|
|
|
||
|
|
// Multicast:
|
||
|
|
Action<string> a;
|
||
|
|
a = Console.WriteLine;
|
||
|
|
a += (s) => Console.WriteLine(s.ToUpper());
|
||
|
|
a += (s) => Console.WriteLine(s.Substring(0, s.Length / 2));
|
||
|
|
|
||
|
|
a.Invoke("Hallo, Welt!"); // Alle zugewiesenen Methoden werden nacheinander aufgerufen.
|
||
|
|
|
||
|
|
Delegate[] invocationList = a.GetInvocationList();
|
||
|
|
invocationList[1].DynamicInvoke("Dynamisch aufgerufen");
|
||
|
|
}
|
||
|
|
|
||
|
|
//Ein Sortieralgorithmus, bei dem durch Übergabe des Delegates bestimmt wird, wie sortiert werden soll (Aufsteigend oder Absteigend)
|
||
|
|
public static void BubbleSort(int[] array, Vergleich vergleich)
|
||
|
|
{
|
||
|
|
if (vergleich == null) // Wir prüfen zuerst, ob überhaupt eine Methode übergeben wurde...
|
||
|
|
return;
|
||
|
|
|
||
|
|
|
||
|
|
for (int i = 0; i < array.Length; i++)
|
||
|
|
{
|
||
|
|
for (int j = 0; j < array.Length - 1 - i; j++)
|
||
|
|
{
|
||
|
|
if (vergleich(array[j], array[j + 1]) == 1) // Aufruf der Methode im Delegate. Dazu können wir den Delegate wie eine Methode verwenden.
|
||
|
|
{
|
||
|
|
// Zwei Elemente tauschen:
|
||
|
|
/*int temp = array[j];
|
||
|
|
array[j] = array[j + 1];
|
||
|
|
array[j + 1] = temp;*/
|
||
|
|
|
||
|
|
// Der Tausch von zwei Variablen in einem Schritt über Tupel:
|
||
|
|
(array[j], array[j + 1]) = (array[j + 1], array[j]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// EventHandler-Methode: Diese muss zur Signatur des EventHandler-Delegaten passen.
|
||
|
|
public static void ButtonClicked(object? sender, EventArgs e)
|
||
|
|
{
|
||
|
|
Console.WriteLine((sender as Button)?.Text);
|
||
|
|
Console.WriteLine("Der Klick wurde verarbeitet...");
|
||
|
|
}
|
||
|
|
}
|