IEnumerable<T>
représente un curseur avant uniquement de T
. .NET 3.5 a ajouté des méthodes d'extension qui incluaient les éléments LINQ standard query operators
similaires Where
et First
, avec tous les opérateurs nécessitant des prédicats ou des fonctions anonymes Func<T>
.
IQueryable<T>
implémente les mêmes opérateurs de requête standard LINQ, mais accepte les Expression<Func<T>>
prédicats et les fonctions anonymes. Expression<T>
est un arbre d'expression compilé, une version fragmentée de la méthode ("à moitié compilée" si vous voulez) qui peut être analysée par le fournisseur de l'interrogation et utilisée en conséquence.
Par exemple:
IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
Dans le premier bloc, se x => x.Age > 18
trouve une méthode anonyme ( Func<Person, bool>
), qui peut être exécutée comme n'importe quelle autre méthode. Enumerable.Where
exécutera la méthode une fois pour chaque personne, en yield
ingérant les valeurs pour lesquelles la méthode est retournée true
.
Dans le deuxième bloc, se x => x.Age > 18
trouve un arbre d'expression ( Expression<Func<Person, bool>>
), qui peut être considéré comme "est la propriété 'Age'> 18".
Cela permet à des éléments tels que LINQ-to-SQL d'exister car ils peuvent analyser l'arborescence des expressions et la convertir en SQL équivalent. Et comme le fournisseur n'a pas besoin d'exécuter jusqu'à ce que le IQueryable
soit énuméré (il implémente IEnumerable<T>
, après tout), il peut combiner plusieurs opérateurs de requête (dans l'exemple ci-dessus Where
et FirstOrDefault
) pour faire des choix plus intelligents sur la façon d'exécuter la requête entière sur les données sous-jacentes source (comme l'utilisation SELECT TOP 1
en SQL).
Voir: