Ich habe die Microsoft Lambda Expression- Dokumentation schnell gelesen .
Diese Art von Beispiel hat mir jedoch geholfen, besser zu verstehen:
delegate int del(int i);
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25
Trotzdem verstehe ich nicht, warum es so eine Innovation ist. Es ist nur eine Methode, die stirbt, wenn die "Methodenvariable" endet, oder? Warum sollte ich dies anstelle einer echten Methode verwenden?
delegate
in C # ist, empfehle ich dringend, dies zu lesen, bevor Sie den Rest dieser Seite lesenAntworten:
Lambda-Ausdrücke sind eine einfachere Syntax für anonyme Delegaten und können überall dort verwendet werden, wo ein anonymer Delegat verwendet werden kann. Das Gegenteil ist jedoch nicht der Fall; Lambda-Ausdrücke können in Ausdrucksbäume konvertiert werden, was viel Magie wie LINQ to SQL ermöglicht.
Das Folgende ist ein Beispiel für einen LINQ to Objects- Ausdruck, bei dem anonyme Delegaten und dann Lambda-Ausdrücke verwendet werden, um zu zeigen, wie viel einfacher für das Auge sie sind:
Lambda-Ausdrücke und anonyme Delegaten haben gegenüber dem Schreiben einer separaten Funktion den Vorteil, dass sie Schließungen implementieren, mit denen Sie den lokalen Status an die Funktion übergeben können, ohne der Funktion Parameter hinzuzufügen oder Objekte zur einmaligen Verwendung zu erstellen.
Ausdrucksbäume sind eine sehr leistungsstarke neue Funktion von C # 3.0, mit der eine API die Struktur eines Ausdrucks anzeigen kann, anstatt nur einen Verweis auf eine Methode zu erhalten, die ausgeführt werden kann. Eine API muss lediglich einen Delegatenparameter in einen
Expression<T>
Parameter umwandeln, und der Compiler generiert einen Ausdrucksbaum aus einem Lambda anstelle eines anonymen Delegaten:genannt wie:
wird:
Letzterem wird eine Darstellung des abstrakten Syntaxbaums übergeben , der den Ausdruck beschreibt
x > 5
. LINQ to SQL basiert auf diesem Verhalten, um C # -Ausdrücke in die SQL-Ausdrücke umwandeln zu können, die zum Filtern / Ordnen / usw. auf der Serverseite gewünscht werden.quelle
Anonyme Funktionen und Ausdrücke sind nützlich für einmalige Methoden, die nicht von der zusätzlichen Arbeit profitieren, die zum Erstellen einer vollständigen Methode erforderlich ist.
Betrachten Sie dieses Beispiel:
gegen
Diese sind funktional gleichwertig.
quelle
Ich fand sie nützlich in einer Situation, in der ich einen Handler für das Ereignis eines Steuerelements mit einem anderen Steuerelement deklarieren wollte. Um dies normal zu tun, müssten Sie die Referenzen der Steuerelemente in Feldern der Klasse speichern, damit Sie sie in einer anderen Methode als der erstellten verwenden können.
Dank Lambda-Ausdrücken können Sie es folgendermaßen verwenden:
Viel einfacher.
quelle
Lambda hat die anonyme Delegatensyntax von C # 2.0 bereinigt ... zum Beispiel
Wurde in C # 2.0 folgendermaßen erstellt:
Funktionell machen sie genau das Gleiche, es ist nur eine viel präzisere Syntax.
quelle
Dies ist nur eine Möglichkeit, einen Lambda-Ausdruck zu verwenden. Sie können einen Lambda-Ausdruck überall dort verwenden, wo Sie einen Delegaten verwenden können. Auf diese Weise können Sie Folgendes tun:
Dieser Code durchsucht die Liste nach einem Eintrag, der dem Wort "Hallo" entspricht. Die andere Möglichkeit besteht darin, einen Delegaten wie folgt an die Find-Methode zu übergeben:
EDIT :
In C # 2.0 kann dies mithilfe der anonymen Delegatensyntax erfolgen:
Lambda hat diese Syntax erheblich aufgeräumt.
quelle
string
und a zurückgibtbool
) als Parameter für dieFind
Methode selbst.Microsoft hat uns eine sauberere und bequemere Möglichkeit gegeben, anonyme Delegaten zu erstellen, die als Lambda-Ausdrücke bezeichnet werden. Dem Ausdrucksteil dieser Aussage wird jedoch nicht viel Aufmerksamkeit geschenkt . Microsoft hat einen vollständigen Namespace, System.Linq.Expressions , veröffentlicht , der Klassen zum Erstellen von Ausdrucksbäumen basierend auf Lambda-Ausdrücken enthält. Ausdrucksbäume bestehen aus Objekten, die Logik darstellen. Beispielsweise ist x = y + z ein Ausdruck, der Teil eines Ausdrucksbaums in .Net sein kann. Betrachten Sie das folgende (einfache) Beispiel:
Dieses Beispiel ist trivial. Und ich bin sicher, Sie denken: "Dies ist nutzlos, da ich den Delegaten direkt hätte erstellen können, anstatt einen Ausdruck zu erstellen und ihn zur Laufzeit zu kompilieren." Und du hättest recht. Dies bildet jedoch die Grundlage für Ausdrucksbäume. In den Expressions-Namespaces stehen eine Reihe von Ausdrücken zur Verfügung, und Sie können Ihre eigenen erstellen. Ich denke, Sie können sehen, dass dies nützlich sein kann, wenn Sie nicht genau wissen, wie der Algorithmus zum Zeitpunkt des Entwurfs oder der Kompilierung aussehen soll. Ich habe irgendwo ein Beispiel dafür gesehen, wie man damit einen wissenschaftlichen Taschenrechner schreibt. Sie können es auch für Bayes'sche Systeme oder für die genetische Programmierung verwenden(AI). Einige Male in meiner Karriere musste ich Excel-ähnliche Funktionen schreiben, mit denen Benutzer einfache Ausdrücke (Additionen, Subtrationen usw.) eingeben konnten, um mit verfügbaren Daten zu arbeiten. In Pre-.Net 3.5 musste ich auf eine Skriptsprache außerhalb von C # zurückgreifen oder die Code-emittierende Funktion in Reflection verwenden, um .Net-Code im laufenden Betrieb zu erstellen. Jetzt würde ich Ausdrucksbäume verwenden.
quelle
Es erspart es, dass Methoden, die nur einmal an einem bestimmten Ort verwendet werden, weit entfernt von dem Ort definiert werden, an dem sie verwendet werden. Gute Verwendungszwecke sind Komparatoren für generische Algorithmen wie das Sortieren, bei denen Sie dann eine benutzerdefinierte Sortierfunktion definieren können, bei der Sie die Sortierung aufrufen, anstatt sich weiter entfernt zu zwingen, woanders zu suchen, um zu sehen, wonach Sie sortieren.
Und es ist nicht wirklich eine Innovation. LISP hat seit ungefähr 30 Jahren oder länger Lambda-Funktionen.
quelle
Sie können auch die Verwendung von Lambda-Ausdrücken beim Schreiben generischer Codes finden, um auf Ihre Methoden zu reagieren.
Beispiel: Generische Funktion zur Berechnung der Zeit, die ein Methodenaufruf benötigt. (dh
Action
hier drin)Und Sie können die obige Methode mit dem Lambda-Ausdruck wie folgt aufrufen:
Mit Expression können Sie den Rückgabewert von Ihrer Methode und auch von out param abrufen
quelle
Der Lambda-Ausdruck ist eine prägnante Möglichkeit, eine anonyme Methode darzustellen. Sowohl anonyme Methoden als auch Lambda-Ausdrücke ermöglichen es Ihnen, die Methodenimplementierung inline zu definieren. Bei einer anonymen Methode müssen Sie jedoch ausdrücklich die Parametertypen und den Rückgabetyp für eine Methode definieren. Der Lambda-Ausdruck verwendet die Typinferenzfunktion von C # 3.0, mit der der Compiler den Typ der Variablen basierend auf dem Kontext ableiten kann. Es ist sehr praktisch, weil wir dadurch viel tippen müssen!
quelle
Ein Lambda-Ausdruck ist wie eine anonyme Methode, die anstelle einer Delegateninstanz geschrieben wurde.
Betrachten Sie den Lambda-Ausdruck
x => x * x;
Der Code eines Lambda-Ausdrucks kann ein Anweisungsblock anstelle eines Ausdrucks sein.
Beispiel
Hinweis:
Func
ist ein vordefinierter generischer Delegat.Verweise
quelle
In vielen Fällen verwenden Sie die Funktionalität nur an einem Ort, sodass eine Methode die Klasse nur überfüllt.
quelle
Auf diese Weise können Sie kleine Operationen ausführen und sie sehr nahe an den Verwendungsort bringen (ähnlich wie beim Deklarieren einer Variablen in der Nähe ihres Verwendungspunkts). Dies soll Ihren Code lesbarer machen. Indem Sie den Ausdruck anonymisieren, erschweren Sie es jemandem erheblich, Ihren Client-Code zu beschädigen, wenn die Funktion an einer anderen Stelle verwendet und geändert wird, um ihn zu "verbessern".
In ähnlicher Weise, warum müssen Sie foreach verwenden? Sie können alles in foreach mit einer Plain-for-Schleife oder einfach mit IEnumerable direkt ausführen. Antwort: Sie brauchen es nicht , aber es macht Ihren Code besser lesbar.
quelle
Die Innovation liegt in der Typensicherheit und Transparenz. Obwohl Sie keine Arten von Lambda-Ausdrücken deklarieren, werden sie abgeleitet und können von der Codesuche, statischen Analyse, Refactoring-Tools und Laufzeitreflexion verwendet werden.
Zum Beispiel, bevor Sie möglicherweise SQL verwendet haben und einen SQL-Injection-Angriff erhalten haben, weil ein Hacker eine Zeichenfolge übergeben hat, an der normalerweise eine Zahl erwartet wurde. Jetzt würden Sie einen LINQ-Lambda-Ausdruck verwenden, der davor geschützt ist.
Das Erstellen einer LINQ-API auf reinen Delegaten ist nicht möglich, da vor der Auswertung Ausdrucksbäume miteinander kombiniert werden müssen.
Im Jahr 2016 haben die meisten populären Sprachen Unterstützung für Lambda-Ausdrücke , und C # war einer der Pioniere in dieser Entwicklung unter den wichtigsten imperativen Sprachen.
quelle
Dies ist vielleicht die beste Erklärung, warum Lambda-Ausdrücke verwendet werden sollten -> https://youtu.be/j9nj5dTo54Q
Zusammenfassend lässt sich sagen, dass die Lesbarkeit des Codes verbessert, das Fehlerrisiko durch Wiederverwendung und nicht durch Replikation von Code verringert und die Optimierung hinter den Kulissen wirksam eingesetzt werden soll.
quelle
Der größte Vorteil von Lambda-Ausdrücken und anonymen Funktionen besteht darin, dass der Client (Programmierer) einer Bibliothek / eines Frameworks Funktionen mithilfe von Code in die angegebene Bibliothek / das angegebene Framework einfügen kann (da es sich um LINQ, ASP.NET Core und handelt) viele andere) auf eine Weise, die die regulären Methoden nicht können. Ihre Stärke ist jedoch nicht für einen einzelnen Anwendungsprogrammierer offensichtlich, sondern für denjenigen, der Bibliotheken erstellt, die später von anderen verwendet werden, die das Verhalten des Bibliothekscodes konfigurieren möchten, oder für diejenigen, die Bibliotheken verwenden. Der Kontext für die effektive Verwendung eines Lambda-Ausdrucks ist also die Verwendung / Erstellung einer Bibliothek / eines Frameworks.
Da sie den Code für die einmalige Verwendung beschreiben, müssen sie nicht Mitglied einer Klasse sein, in der dies zu einer höheren Codekomplexität führt. Stellen Sie sich vor, Sie müssen jedes Mal eine Klasse mit unklarem Fokus deklarieren, wenn wir den Betrieb eines Klassenobjekts konfigurieren möchten.
quelle