Es gibt zwei wichtige Schritte zum Kompilieren einer LINQ-Abfrage in C #. Die erste besteht in der Umwandlung der LINQ-Abfragesyntax in eine Kette von Methodenaufrufen, wie in Abschnitt 7.16 der C # -Sprachenspezifikation beschrieben. Dieser Transformationsprozess ist so detailliert spezifiziert, dass ein Sprachentwickler damit eine ähnliche Abfragesyntax in einer neuen CLR-Sprache implementieren kann.
Der zweite Schritt besteht darin, Lambda-Ausdrücke in Ausdrucksbäume umzuwandeln. Dies geschieht beim Aufruf einer Abfrage-Methode, die IQueryable
zurückgibt, aber nicht beim Aufruf einer Methode, die IEnumerable
zurückgibt. Ist es jemals spezifiziert, wie diese Transformation stattfindet, vergleichbar mit der Erklärung der Transformation der Abfrage-Syntax?
Die Konstruktion von Ausdrucksbäumen ist eigentlich nicht definiert. Compiler-Entwickler können frei wählen, was sie wollen, vorausgesetzt natürlich, dass das Ausführen des Ausdrucks das gleiche Ergebnis liefert wie das Aufrufen des Lambda.
Dies ist ein Zitat aus der C # -Sprachspezifikation:
6.5.2 Auswertung von anonymen Funktionskonvertierungen in Ausdrucksbaumtypen
Die Umwandlung einer anonymen Funktion in einen Ausdrucksbaumtyp erzeugt einen Ausdrucksbaum (§4.6). Genauer gesagt führt die Auswertung der anonymen Funktionskonvertierung zur Konstruktion einer Objektstruktur, die die Struktur der anonymen Funktion selbst darstellt. Die genaue Struktur des Ausdrucksbaums sowie der genaue Prozess für die Erstellung des Ausdrucksbaums sind in der Implementierung definiert.
Ich habe das Fett am Ende hinzugefügt.
Ich vermute, dass dies absichtlich nicht spezifiziert wurde, um Compiler-Entwicklern die Freiheit zu geben, alle ihnen nützlichen Optimierungen zu implementieren. Eine starre Spezifikation des Ausdrucksbaums würde das verhindern.
Ist es jemals spezifiziert, wie diese Transformation stattfindet, vergleichbar? zur Erklärung der Transformation der Abfrage Syntax?
Wie NSFW gesagt hat, nein.
Praktisch können diese Ausdrucksbäume von Framework zu Framework wechseln. Ein Beispiel aus dem wirklichen Leben wäre das:
Wir haben expression lambdas
verwendet, um die Eigenschafteninformationen über Ausdrucksbäume zu erhalten.
Wie void DoSomething<P, K>(P model, Expression<Func<P, K> propertySelector)
und die Verwendung DoSomething(model, m => m.Property)
Die eigentliche Immobilienabfrage wurde innerhalb von DoSomething
durch Reflexion durchgeführt. Das ist sehr klassisch, und Varianten dieses Codes existieren über das Internet.
Nun, das ist cool, es hat in .NET 4.0 gut funktioniert. Sobald ich jedoch 4.5 getestet habe, explodierte es vollständig, da sich der zugrunde liegende Ausdrucksbaum geändert hat.
Sie können sicher sein, dass Roslyn viele neue "Bugs" einführen wird, in dem Sinne, dass einige Client-Codes auf der Darstellung von Lambdas in Ausdrucksbäumen basieren (wenn Sie darauf bestehen, dass Visitor
class minimiert) die Chancen zu brechen).
Sicherzustellen, dass die Ausdrucksbäume gleich bleiben, wäre eine große Aufgabe, und sie wäre auch einschränkend (zum Beispiel in Bezug auf die Geschwindigkeit)
Tags und Links .net c# linq language-specifications