7.7 Lambda-Ausdrücke 

In Kapitel 5, »Delegates und Ereignisse«, hatte ich Ihnen im Zusammenhang mit den Delegates das Beispielprogramm AnonymeMethoden vorgestellt. Zur Erinnerung: An der Konsole wurde der Anwender zur Eingabe von zwei Zahlen aufgefordert. Anschließend konnte der Benutzer entscheiden, ob er die beiden Zahlen addieren oder subtrahieren möchte. Später wurden im gleichen Kapitel anstelle der Delegates anonyme Methoden verwendet. Hier ist noch einmal die Passage, die für uns im Weiteren von Interesse ist:
... if (wahl == "A") calculate = delegate(double x, double y) { return x + y; }; else if (wahl == "S") calculate = delegate(double x, double y) { return x - y; }; else { Console.Write("Ungültige Eingabe"); Console.ReadLine(); return; } ...
Bei einem Lambda-Ausdruck handelt es sich um eine anonyme Methode, die Ausdrücke und Anweisungen enthalten und für die Erstellung von Delegates verwendet werden kann.
Mithilfe von Lambda-Ausdrücken können Sie den Code von oben auch wie folgt formulieren:
... if (wahl == "A") calculate = (double x, double y) => { return x + y;}; else if (wahl == "S") calculate = (double x, double y) => { return x - y; }; ...
Die beiden Lambda-Ausdrücke in diesem Codefragment sind
(double x, double y) => { return x + y;};
und
(double x, double y) => { return x - y; }
Lambda-Ausdrücke verwenden den Operator =>. Links davon werden die Eingabeparameter angegeben, rechts davon der Ausdruck oder ein Anweisungsblock. Das in der ursprünglichen Fassung vorhandene Schlüsselwort delegate taucht nicht mehr auf.
Der Anweisungsrumpf eines Lambda-Ausdrucks benötigt eine geschweifte Klammer wie jeder andere Anweisungsblock auch und kann beliebig viele Anweisungen enthalten. Häufig anzutreffen sind Lambda-Ausdrücke, deren einzige Anweisung ein return ist. In einem solchem Fall dürfen Sie die return-Anweisung weglassen und können gleichzeitig auch auf die geschweiften Klammern verzichten.
... if (wahl == "A") calculate = (double x, double y) => x + y; else if (wahl == "S") calculate = (double x, double y) => x - y; ...
Bisher scheint es so zu sein, dass die Einführung der Lambda-Ausdrücke nur rein syntaktischer Natur ist. Dem ist aber nicht so. Sehen Sie sich dazu das folgende Codefragment an:
... if (wahl == "A") calculate = (x, y) => x + y; else if (wahl == "S") calculate = (x, y) => x - y; ...
Beachten Sie, dass nun die Angabe der Parametertypen entfernt worden ist. Es handelt sich jetzt um implizit typisierte Parameter, und der Compiler leitet die Parametertypen richtig ab. Vorausgesetzt werden muss dabei natürlich, dass der Operator + für den konkreten Typ von x und y definiert ist. In unserem Beispiel ist das der Fall.
Der Lambda-Ausdruck
(x, y) => x + y
hat zwei Parameter, die in runden Klammern eingeschlossen und durch ein Komma getrennt sind. Liegt nur ein Parameter vor, können die runden Klammern aus der Parameterliste entfernt werden:
x => x + x
Bei einem Lambda-Ausdruck mit leerer Parameterliste müssen jedoch die runden Klammen angegeben werden:
() => a * b
Ein Lambda-Ausdruck, der lediglich eine return-Anweisung enthält, wird als Ausdrucksrumpf bezeichnet.
Projektion und Prädikat
Der Datentyp der Rückgabe eines Lambda-Ausdrucks kann sich vom Datentyp des Parameters unterscheiden. Liegt ein solcher Lambda-Ausdruck vor, wird von einer Projektion gesprochen. Die folgende Anweisung zeigt eine solche. Dabei wird eine Zeichenfolge übergeben und deren Länge geprüft. Der Rückgabewert ist vom Typ Integer.
(str) => str.Length
Ein Prädikat hingegen liefert einen booleschen Wert als Ergebnis einer Operation:
(alter) => alter > 65