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
ing значення, для яких метод повернувся true
.
У другому блоці x => x.Age > 18
- дерево виразів ( Expression<Func<Person, bool>>
), яке можна розглядати як "є властивістю" Age "> 18".
Це дозволяє існувати такі речі, як LINQ-SQL, оскільки вони можуть аналізувати дерево виразів і перетворювати його в еквівалентний SQL. І оскільки постачальнику не потрібно виконувати, поки не IQueryable
буде перераховано (він реалізує IEnumerable<T>
, зрештою), він може об'єднати декілька операторів запитів (у наведеному вище прикладі Where
та FirstOrDefault
), щоб зробити більш розумний вибір щодо виконання всього запиту щодо базових даних джерело (наприклад, використання SELECT TOP 1
в SQL).
Побачити: