Die Zuordnung einer Funktion zu einem Ausdruck und Umgekehrt
War ich Manipulationen mit Ausdrücken und ich war verwirrt an einigen stellen
-
Können wir zuordnen gleichen LamdaExpression sowohl die Expression und/oder Func. Aber wir können nicht zuordnen einer Funktion zu einem Ausdruck (oder ein Ausdruck, Func). Warum kann nicht wir das tun? Ich sah, wenn eine conversion operator zwischen Ausdruck und Func definiert ist, aber ich konnte keine gefunden.
Func<int, int> sumFunc = i => i + i; Expression<Func<int, int>> sumExp = i => i + i; //sumExp = sumFunc; //Cannot convert source type 'System.Func<int,int>' to target type 'System.Linq.Expressions.Expression<System.Func<int,int>>' //sumFunc = sumExp; //Cannot convert source type 'System.Linq.Expressions.Expression<System.Func<int,int>>' to target type 'System.Func<int,int>'
-
Selbst können wir nicht zuordnen LambdaExpression auf ein Objekt. Wieder, warum wir nicht das tun?
//object o = i => i + i; //Cannot convert source type 'lambda expression' to target type 'object'
-
Ich denke, es ist etwas über compiler. Wenn dem so ist, können wir schreiben unsere benutzerdefinierte Typen diese Verhalten sich in dieser (verwirrenden) Art und Weise und nutzen etwas.
- Sie können Aufruf von compile() auf einen Ausdruck-Baum zu bekommen func. Der andere Weg ist weitgehend unmöglich: es erfordert ein AST, das ist sehr schwer zu konstruieren zu beliebigem IL
Du musst angemeldet sein, um einen Kommentar abzugeben.
Bezug auf die C# - Programmiersprachenspezifikation ein lambda-Ausdruck wie
ist eine anonyme Funktion. Ein Ausdruck mit dieser Klassifizierung kann implizit in einen kompatiblen delegate-Typ oder einen Ausdruck-Baum geben. Das ist, warum Sie schreiben beide
Das erste ist ein delegate-Typ, das zweite ein Ausdruck Baum-Typ. Da es keine implizite Umwandlung zwischen diesen Typen, die Sie nicht zuordnen können
sumFunc = sumExp
oder Umgekehrt. Aber da die expression treesumExp
stellt einen lambda-Ausdruck, können Sie kompilieren Sie diesen Ausdruck, um eine ausführbare Datei zu delegieren und zuweisensumFunc
, weil dies ein so kompatibel delegieren:Die andere Richtung ist nicht möglich, weil ein Delegat kann nicht leicht sein "dekompiliert" in einen Ausdruck-Baum.
Den Grund, warum Sie nicht schreiben kann
ist, dass eine anonyme Funktion keinen Wert, oder geben Sie in und von sich selbst, es ist nur umwandelbar zu einem Delegierten-oder expression-Baum-Typ. Sie sagen dem compiler mit, welcher der beiden Sie möchten, so können Sie wandeln es auf den ersten und weisen das Ergebnis einer variable vom Typ
object
:Bezüglich Ihrer letzten Frage: Sie können benutzerdefinierte implizite oder explizite Konvertierungen zwischen komplexen Typen, so dass diese "Magie" angewendet werden können, um Zuordnungen. Finden Sie die Umwandlung Operationen Programming Guide für weitere Informationen.
Tatsächlich diese beiden Ausdrücke sind syntax-Zucker, verwandelt durch den compiler in verschiedene Sprachkonstrukte.
Beim schreiben lambda-Ausdruck, der compiler tut dies: macht die member-Funktion passt lamda-Ausdruck und weist Sie auf Ihre sumFunc variable (dies ist nicht der exakte code, nur um eine Vorstellung zu bekommen):
Wenn Sie schreiben, Ausdruck Baum gibt es noch mehr Magie passiert. Zur compile-Zeit compiler verwandelt Ihren Ausdruck in den Ausdruck ein Baum "Konstruktion". Wie diese.
Du sehen, dass dies völlig verschiedene Dinge, das ist, warum können Sie nicht einfach werfen einem zum anderen.
Ausdruck eine Abstraktion ist. Es ermöglicht Linq zum effizienten erstellen von SQL-Abfragen für Datenbanken, XML, oder für eine andere Datenquelle. Es ist ähnlich im Konzept zu einem abstrakten syntax Baum, speichert es die syntaktischen Elemente von der Abfrage, damit die Linq-Anbieter können eine Abfrage erstellen.
Wenn es funktioniert, wie Sie erwarten, was Sie würde tun müssen, nehmen Sie den abstract syntax tree von der lambda-Funktion und generiert einen Baum, der Ausdruck der Objekte. Gut, das ist nicht wirklich möglich, soweit ich weiß, und was gut wäre es, sowieso?