Verwenden von Lambda Expressions-Bäumen mit IEnumerable

8

Ich habe versucht, mehr über die Verwendung von Lamba-Ausdrucksbäumen zu erfahren, und so habe ich ein einfaches Beispiel erstellt. Hier ist der Code, der in LINQPad funktioniert, wenn er als C # -Programm eingefügt wird.

%Vor%

Dies führt zu dem folgenden Fehler:

Die Typargumente für die Methode 'System.Linq.Enumerable.Where (System.Collections.Generic.IEnumerable, System.Func)' können nicht aus der Verwendung abgeleitet werden. Versuchen Sie, die Typargumente explizit anzugeben.

Aber wenn ich nur die erste Zeile in main mit dieser ersetzen:

%Vor%

Es funktioniert gut. Kann mir bitte sagen, was ich falsch mache?

    
Loathian 07.03.2010, 20:41
quelle

4 Antworten

5

Die Methode Enumerable.Where benötigt Func<T, bool> , nicht Expression<Func<T, bool>> . Vielleicht verwirrend mit Queryable.Where , das einen Ausdruck als Parameter akzeptiert ... In Ihrem Fall brauchen Sie keinen Ausdruck, Sie brauchen nur einen Delegaten, der für jedes Element in der Sequenz ausgeführt werden kann. Der Zweck von Ausdrücken ist (meistens) zu analysieren und zu etwas anderem zu übersetzen (zum Beispiel SQL), um die Abfrage gegen eine externe Datenquelle durchzuführen

    
Thomas Levesque 07.03.2010, 20:44
quelle
1

Ändern Sie den Rückgabetyp von NameContains von Expression<Func<User, Bool>> in einfach Func<User, Bool> . In dieser Situation müssen Sie den Ausdruck nicht zurückgeben, Sie möchten den kompilierten Delegaten tatsächlich zurückgeben. Es gibt einen Unterschied zwischen dem Ausdruck, der das Lambda bildet, und dem Lambda (das ein Delegierter ist).

Wenn Sie ein Lambda in eine Methode senden, kann die Methode das Lambda entweder als Ausdruck oder als kompilierten Delegattyp akzeptieren, je nachdem, was Sie in den Parametern angeben. Wenn der Typ des eingehenden Parameters ein Ausdruck ist, können Sie etwas senden, das wie ein Delegat aussieht. Wenn die Methode jedoch einen Delegaten erwartet, müssen Sie ihm einen kompilierten Delegaten und nicht einfach einen Ausdruck geben. Davon abgesehen können Sie auch Folgendes tun:

%Vor%

Dies würde den Ausdruck zusammenstellen und ein Func<User, Bool> zurückgeben.

    
David Morton 07.03.2010 20:42
quelle
0

Lambda-Ausdrücke können entweder als Code (Delegaten) oder als Daten (Ausdrucksbäume) behandelt werden.

In Ihrem Beispiel versuchen Sie, den Lambda-Ausdruck als Code zu behandeln.

Sie würden den Ausdruck & lt; & gt; Erklärung, wenn Sie den Lambda-Ausdruck als Daten behandeln möchten.

Warum möchten Sie das tun?

Hier ist ein Zitat aus dem Buch Linq In Action,

"Ausdrucksbäume können zur Laufzeit an Werkzeuge übergeben werden, die sie zur Orientierung verwenden ihre Ausführung oder übersetzen sie in etwas anderes, wie SQL im Falle von LINQ to SQL. "

Mit Expression Trees können Sie den Lambda-Ausdruck verwenden und ihn in Daten konvertieren. So funktioniert Linq to SQL, er nimmt den Lambda-Ausdruck oder die Abfrageoperatoren oder Abfrageausdrücke und konvertiert sie in SQL. Natürlich können Sie den erstellten Ausdrucksbaum anzeigen und ändern, sobald er in sql konvertiert wurde.

    
Joe Pitz 07.03.2010 21:03
quelle
0

Es gibt einen großen Unterschied zwischen Expression und Func & lt; ... & gt ;, der Func ist ein reiner Delegat, den Sie direkt aufrufen können, der Ausdruck ist eine Datenstruktur enthält Informationen über einen Ausdruck wie Informationen über Lambda-Ausdruck oder Linq-Syntax (zB Von x in Liste, wo x.Id = 1 x wählen). Der Ausdruck kann nicht direkt aufgerufen werden, er muss zuerst kompiliert werden, Ausdrücke werden verwendet, um den Ausdruck von einem Weg in einen anderen wie Link zu Sql zu konvertieren, der einen Ausdruck in Sql-Anweisungen umwandelt, um den Rückgabetyp der NameContains zu ändern Die Methode funktioniert nicht mit Ausdruck, da Sie mit Linq To Objects arbeiten, aber wenn Sie mit Linq To Sql arbeiten, können Sie sowohl Expression als auch func verwenden.

    
Mina W Alphonce 11.02.2011 09:15
quelle

Tags und Links