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).
Видеть: