Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Ausdrucksstrukturen stellen Code in einer baumartigen Datenstruktur dar, wobei jeder Knoten ein Ausdruck ist, z. B. ein Methodenaufruf oder ein binärer Vorgang, wie x < y.
Wenn Sie LINQ verwendet haben, haben Sie Erfahrung mit einer umfangreichen Bibliothek, in der die Func Typen Teil des API-Satzes sind. (Wenn Sie mit LINQ nicht vertraut sind, sollten Sie wahrscheinlich das LINQ-Lernprogramm und den Artikel zu Lambda-Ausdrücken vor diesem Thema lesen.) Ausdrucksstrukturen bieten eine umfassendere Interaktion mit den Argumenten, die Funktionen sind.
Sie schreiben Funktionsargumente, in der Regel mithilfe von Lambda-Ausdrücken, wenn Sie LINQ-Abfragen erstellen. In einer typischen LINQ-Abfrage werden diese Funktionsargumente in einen Delegaten transformiert, den der Compiler erstellt.
Sie schreiben bereits Code, der Ausdrucksbäume verwendet. Die LINQ-APIs von Entity Framework akzeptieren Expression Trees als Argumente für das LINQ-Abfragemuster. Dadurch kann Entity Framework die in C# geschriebene Abfrage in SQL übersetzen, die im Datenbankmodul ausgeführt wird. Ein weiteres Beispiel ist Moq, ein beliebtes Mocking-Framework für .NET.
Wenn Sie eine reichhaltigere Interaktion wünschen, müssen Sie Ausdrucksbäume verwenden. Expressionsbäume stellen Code als Struktur dar, die Sie untersuchen, ändern oder ausführen können. Mit diesen Tools können Sie Code während der Laufzeit bearbeiten. Sie schreiben Code, der ausgeführte Algorithmen untersucht oder neue Funktionen eingibt. In komplexeren Szenarien ändern Sie ausgeführte Algorithmen und übersetzen sogar C#-Ausdrücke in ein anderes Formular für die Ausführung in einer anderen Umgebung.
Sie kompilieren und ausführen Code, der durch Ausdrucksstrukturen dargestellt wird. Das Erstellen und Ausführen von Ausdrucksbäumen ermöglicht die dynamische Änderung von ausführbarem Code, die Ausführung von LINQ-Abfragen in verschiedenen Datenbanken und die Erstellung dynamischer Abfragen. Weitere Informationen zu Ausdrucksstrukturen in LINQ finden Sie unter Verwenden von Ausdrucksstrukturen zum Erstellen dynamischer Abfragen.
Ausdrucksbaumstrukturen werden auch in der Dynamic Language Runtime (DLR) verwendet, um Interoperabilität zwischen dynamischen Sprachen und .NET zu gewährleisten. Dies ermöglicht Entwicklern von Compilern, Ausdrucksbaumstrukturen anstelle der Microsoft Intermediate Language (CIL) auszugeben. Weitere Informationen zur DLR finden Sie unter Übersicht über die Dynamic Language Runtime.
Sie können mit dem C#- oder Visual Basic-Compiler eine Ausdrucksstruktur für Sie erstellen, die auf einem anonymen Lambda-Ausdruck basiert, oder Sie können Ausdrucksstrukturen manuell mithilfe des System.Linq.Expressions Namespace erstellen.
Wenn einem Lambda-Ausdruck eine Variable vom Typ Expression<TDelegate>zugewiesen ist, gibt der Compiler Code aus, um eine Ausdrucksstruktur zu erstellen, die den Lambda-Ausdruck darstellt.
Die folgenden Codebeispiele veranschaulichen, wie der C#-Compiler eine Ausdrucksstruktur erstellt, die den Lambda-Ausdruck num => num < 5darstellt.
Expression<Func<int, bool>> lambda = num => num < 5;
Sie erstellen Ausdrucksbäume in Ihrem Code. Sie erstellen den Baum, indem Sie jeden einzelnen Knoten erstellen und die Knoten in eine Baumstruktur einfügen. Im Artikel über das Erstellen von Ausdrucksbäumen lernen Sie, wie Sie Ausdrücke erstellen.
Ausdrucksbäume sind unveränderlich. Wenn Sie eine Ausdrucksstruktur ändern möchten, müssen Sie eine neue Ausdrucksstruktur erstellen, indem Sie die vorhandene Struktur kopieren und Knoten ersetzen. Sie verwenden einen Ausdrucksbaumstruktur-Besucher, um die vorhandene Ausdrucksbaumstruktur zu durchlaufen. Weitere Informationen finden Sie im Artikel zum Übersetzen von Ausdrucksbäumen.
Nachdem Sie eine Ausdrucksstruktur erstellt haben, führen Sie den code aus, der durch die Ausdrucksstruktur dargestellt wird.
Einschränkungen
Der C#-Compiler erstellt Ausdrucksbaumstrukturen nur aus Ausdrucklambdas (oder einzeiligen Lambdas). Es kann keine Anweisungslambdas (oder mehrzeiligen Lambdas) analysieren. Weitere Informationen zu Lambda-Ausdrücken in C# finden Sie unter Lambda-Ausdrücke.
Es gibt einige neuere C#-Sprachfunktionen, die nicht gut in Ausdrucksbäume übersetzt werden. Ausdrucksbaumstrukturen können keine await-Ausdrücke oder async-Lambdaausdrücke enthalten. Viele der Features, die in C# 6 und später hinzugefügt wurden, erscheinen in Ausdrucksbäumen nicht genauso, wie sie geschrieben wurden. Stattdessen werden, wenn möglich, neuere Funktionen in Ausdrucksbaumstrukturen in der entsprechenden früheren Syntax verfügbar gemacht. Andere Konstrukte sind nicht verfügbar. Das bedeutet, dass Code, der Ausdrucksstrukturen interpretiert, auch dann gleich funktioniert, wenn neue Sprachfeatures eingeführt werden. Trotz dieser Einschränkungen ermöglichen es Ausdrucksbäume jedoch, dynamische Algorithmen zu erstellen, die auf dem Interpretieren und Ändern von Code basieren, der als Datenstruktur dargestellt wird. Es ermöglicht umfangreiche Bibliotheken wie Entity Framework, ihre Aufgaben zu erreichen.
Ausdrucksstrukturen unterstützen keine neuen Ausdrucksknotentypen. Es wäre eine fehlerhafte Änderung für alle Bibliotheken, die Ausdrucksbäume interpretieren, neue Knotentypen einzuführen. Die folgende Liste enthält die meisten C#-Sprachelemente, die nicht verwendet werden können:
- Bedingte Methoden , die aus der Ausgabe entfernt wurden
-
baseZugang - Ausdrücke für Methodengruppen, einschließlich Adresse von (
&) einer Methodengruppe und anonyme Methodenausdrücke - Verweise auf lokale Funktionen
- Anweisungen, einschließlich Zuweisungen (
=) und Ausdrücke mit Anweisungs-Body - Partielle Methoden mit nur einer definierenden Deklaration
- Unsichere Zeigervorgänge
-
dynamicTransaktionen -
Zusammenführende Operatoren mit
nulloderdefault-Literalen auf der linken Seite, Zuweisung mit Null zusammenführend und der Null-Propagating-Operator (?.) - Mehrdimensionale Arrayinitialisierer, indizierte Eigenschaften und Wörterbuchinitialisierer
- Sammlungsausdrücke
-
throw-Ausdrücke - Zugreifen auf
static virtualElemente oderabstractSchnittstellen - Lambda-Ausdrücke mit Attributen
- Interpolierte Zeichenfolgen
- UTF-8-Zeichenfolgenumwandlungen oder UTF-8-Zeichenfolgenliterale
- Methodenaufrufe mit variablen Argumenten, benannten Argumenten oder optionalen Argumenten
- Ausdrücke mit System.Index oder System.Range, Operator "von Ende" (
^) oder Bereichsausdrücke (..) -
asyncLambda-Ausdrücke oderawaitAusdrücke, einschließlichawait foreachundawait using -
Tupel-Literale, Tupel-Konversionen, Tupel
==oder!=, oderwithAusdrücke -
Verwerfen von (
_), Dekonstruieren von Zuweisungen, Operator für den Match-Vorgangisoder der Ausdruck für den Match-Vorgangswitch - COM-Aufruf mit weggelassenem
refbei den Argumenten -
ref,inoderoutParameter,refRückgabewerte,outArgumente oder beliebige Werte vomref structTyp