Update: Sie haben Ihren Titel korrigiert, also ignorieren Sie die Schimpftirade.
Der Titel Ihrer Frage hat nichts mit Ihren Codebeispielen zu tun. Ihre Frage impliziert, dass eine Syntax IEnumerable und die andere IQueryable ist, aber das ist falsch. In Ihren Beispielen, wenn db.Surveys
ein IQueryable ist, dann beide Ihre Beispiele sind mit IQueryable. Ich werde versuchen zu antworten beide Fragen.
Ihre beiden Codebeispiele sind nur verschiedene Möglichkeiten, die gleichen LINQ-Abfragen zu schreiben (vorausgesetzt, sie sind gut geschrieben). Der Code in Beispiel 1 ist nur eine Kurzform für den Code in Beispiel 2. Der Compiler behandelt den Code in beiden Beispielen auf dieselbe Weise. Denken Sie an die Art und Weise, wie der C#-Compiler Folgendes behandeln wird int?
dasselbe wie Nullable<System.Int32>
. Sowohl die Sprachen C# als auch VB.Net bieten diese Kurzabfragesyntax. Andere Sprachen verfügen möglicherweise nicht über diese Syntax und Sie müssen die Syntax von Beispiel 2 verwenden. Andere Sprachen unterstützen möglicherweise nicht einmal Erweiterungsmethoden oder Lambda-Ausdrücke, und Sie müssten eine noch hässlichere Syntax verwenden.
Update:
Um das Beispiel von Sander weiterzuführen: Wenn Sie dies schreiben (Syntax für Abfrageverständnis):
var surveyNames = from s in db.Surveys select s.Name
Sie denken verwandelt der Compiler diese Abkürzung in das hier (Erweiterungsmethoden und Lambda-Ausdruck):
IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);
Aber eigentlich sind Erweiterungsmethoden und Lambda-Ausdrücke selbst Kurzschrift. Der Compiler gibt so etwas aus (nicht genau, aber nur um eine Vorstellung zu vermitteln):
Expression<Func<Survey, string>> selector = delegate(Survey s) { return s.Name; };
IQueryable<string> surveryNames = Queryable.Select(db.Surveys, selector);
Beachten Sie, dass Select()
ist lediglich eine statische Methode in der Queryable
Klasse. Wenn Ihre .NET-Sprache keine Abfragesyntax, Lambdas oder Erweiterungsmethoden unterstützt, müssten Sie den Code sozusagen selbst schreiben.
Welche Vorteile hat der eine Stil gegenüber dem anderen?
Bei kleinen Abfragen können die Erweiterungsmethoden kompakter sein:
var items = source.Where(s => s > 5);
Außerdem kann die Syntax der Erweiterungsmethode flexibler sein, z. B. durch bedingte Where-Klauseln:
var items = source.Where(s => s > 5);
if(smallerThanThen)
items = items.Where(s => s < 10);
if(even)
items = items.Where(s => (s % 2) == 0);
return items.OrderBy(s => s);
Außerdem sind mehrere Methoden nur über die Syntax der Erweiterungsmethoden verfügbar (Count(), Aggregate(), Take(), Skip(), ToList(), ToArray() usw.). Wenn ich also eine dieser Methoden verwende, schreibe ich normalerweise die gesamte Abfrage in dieser Syntax, damit ich nicht beide Syntaxen vermische.
var floridaCount = source.Count(s => s.State == "FL");
var items = source
.Where(s => s > 5)
.Skip(5)
.Take(3)
.ToList();
Andererseits, wenn eine Abfrage größer und komplexer wird, kann die Abfrageverstehenssyntax klarer sein, vor allem, wenn man anfängt, sie mit ein paar let
, group
, join
, usw.
Am Ende verwende ich in der Regel das, was für die jeweilige Anfrage am besten geeignet ist.
Update: Sie haben Ihren Titel korrigiert, also ignorieren Sie den Rest...
Nun zu Ihrem Titel: In Bezug auf LINQ sind IEnumerable und IQueryable sehr ähnlich. Sie haben beide so ziemlich die gleichen Erweiterungsmethoden (Select, Where, Count, etc.), wobei der wichtigste (einzige?) Unterschied darin besteht, dass IEnumerable Func<TIn,TOut>
als Paremeter und IQueryable nimmt Expression<Func<TIn,TOut>>
als Parameter. Man drückt beide auf die gleiche Weise aus (in der Regel durch Lamba-Ausdrücke), aber intern sind sie völlig unterschiedlich.
IEnumerable ist das Tor zu LINQ to Objects. Die LINQ to Objects-Erweiterungsmethoden können mit jeder IEnumerable aufgerufen werden (Arrays, Listen, alles, mit dem man iterieren kann foreach
) und die Func<TIn,TOut>
wird zur Kompilierzeit in IL umgewandelt und läuft zur Laufzeit wie ein normaler Methodencode. Beachten Sie, dass einige andere LINQ-Anbieter IEnumerable verwenden und somit hinter den Kulissen tatsächlich LINQ to Objects verwenden (LINQ to XML, LINQ to DataSet).
IQueryable wird von LINQ to SQL, LINQ to Entities und anderen LINQ-Anbietern verwendet, die Ihre Abfrage untersuchen und übersetzen müssen, anstatt Ihren Code direkt auszuführen. IQueryable-Abfragen und ihre Expression<Func<TIn,TOut>>
s werden zur Kompilierzeit nicht in AWL kompiliert. Stattdessen wird eine Ausdrucksbaum wird erstellt und kann zur Laufzeit überprüft werden. Dadurch können die Anweisungen in andere Abfragesprachen (z.B. T-SQL) übersetzt werden. Ein Ausdrucksbaum kann zur Laufzeit in eine Func<TIn,TOut> kompiliert und auf Wunsch ausgeführt werden.
Ein Beispiel, das den Unterschied verdeutlicht, findet sich in この質問 wo der OP einen Teil einer LINQ to SQL-Abfrage in SQL Server ausführen möchte, die Objekte in verwalteten Code bringen und den Rest der Abfrage in LINQ to Objects ausführen möchte. Um dies zu erreichen, muss er nur die IQueryable in eine IEnumerable umwandeln, wo er den Wechsel durchführen möchte.
0 Stimmen
Es ist erwähnenswert, dass Ihre Proben nicht identisch sind ...
0 Stimmen
Auch das .ToList() am Ende erzwingt eine ganz andere Ausführung. Lassen Sie es weg, um sie gleichwertig zu machen. Das erste x ist vom Typ IQueryable<T> und das zweite ist IList<T>.