IEnumerable<T>
представляет курсор только вперед T
. В .NET 3.5 добавлены методы расширения, включающие LINQ standard query operators
подобные Where
и First
со всеми операторами, которые требуют предикатов или анонимных функций Func<T>
.
IQueryable<T>
реализует те же стандартные операторы запросов LINQ, но принимает Expression<Func<T>>
предикаты и анонимные функции. Expression<T>
является скомпилированным деревом выражений, разбитой версией метода (если хотите, «наполовину скомпилированным»), который может быть проанализирован поставщиком запрашиваемого и использован соответствующим образом.
Например:
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();
В первом блоке x => x.Age > 18
находится анонимный метод ( Func<Person, bool>
), который может быть выполнен как любой другой метод. Enumerable.Where
выполнит метод один раз для каждого человека, yield
найдя значения, для которых возвращается метод true
.
Во втором блоке x => x.Age > 18
находится выражение tree ( Expression<Func<Person, bool>>
), которое можно рассматривать как «свойство« Возраст »> 18».
Это позволяет существовать таким вещам, как LINQ-to-SQL, поскольку они могут анализировать дерево выражений и преобразовывать его в эквивалентный SQL. А поскольку провайдеру не нужно выполнять до IQueryable
перечисления (в IEnumerable<T>
конце концов, он реализует ), он может комбинировать несколько операторов запросов (в приведенном выше примере Where
и FirstOrDefault
), чтобы сделать более разумный выбор способов выполнения всего запроса к базовым данным. источник (например, использование SELECT TOP 1
в SQL).
Видеть: