Обновление: вы исправили свой титул, поэтому игнорируйте напыщенную речь.
Название вашего вопроса не имеет ничего общего с вашими примерами кода. Ваш вопрос подразумевает, что один синтаксис IEnumerable, а другой - IQueryable, но это неверно. В ваших примерах, если db.Surveys
является IQueryable, то оба ваши образцы используют IQueryable. Я постараюсь ответить на оба вопросов.
Ваши два примера кода - это просто разные способы написания одних и тех же запросов LINQ (при условии, что они хорошо написаны). Код в примере 1 является просто сокращением для кода в примере 2. Компилятор обрабатывает код в обоих примерах одинаково. Подумайте, как компилятор C # будет обрабатывать int?
так же, как Nullable<System.Int32>
. Оба языка C # и VB.Net предоставляют этот сокращенный синтаксис запроса. Другие языки могут не иметь этот синтаксис, и вам придется использовать пример 2 синтаксиса. Фактически, другие языки могут даже не поддерживать методы расширения или лямбда-выражения, и вам еще придется использовать более уродливый синтаксис.
Обновление:
Чтобы продолжить пример Сандера, когда вы пишете это (синтаксис понимания запроса):
var surveyNames = from s in db.Surveys select s.Name
Вы думаете, компилятор превращает этот сокращенный текст в это (методы расширения и лямбда-выражения):
IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);
Но на самом деле методы расширения и лямбда-выражения сами являются сокращением. Компиляторы испускают что-то вроде этого (не совсем, но просто для того, чтобы дать представление):
Expression<Func<Survey, string>> selector = delegate(Survey s) { return s.Name; };
IQueryable<string> surveryNames = Queryable.Select(db.Surveys, selector);
Обратите внимание, что Select()
- это просто статический метод в классе Queryable
. Если ваш язык .NET не поддерживает синтаксис запросов, лямбда-выражения или методы расширения, то именно так вам и придется писать код самостоятельно.
Каковы преимущества использования одного стиля над другим?
Для небольших запросов методы расширения могут быть более компактными:
var items = source.Where(s => s > 5);
Кроме того, синтаксис метода расширения может быть более гибким, например, условные предложения where:
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);
Кроме того, некоторые методы доступны только через синтаксис метода расширения (Count (), Aggregate (), Take (), Skip (), ToList (), ToArray () и т. Д.), Поэтому, если я буду использовать один из них) из них я обычно пишу весь запрос в этом синтаксисе, чтобы избежать смешивания обоих синтаксисов.
var floridaCount = source.Count(s => s.State == "FL");
var items = source
.Where(s => s > 5)
.Skip(5)
.Take(3)
.ToList();
С другой стороны, когда запрос становится больше и сложнее, синтаксис его понимания может быть более понятным, особенно если вы начнете усложнять несколько let
, group
, join
и т. Д.
В конце я обычно использую то, что работает лучше для каждого конкретного запроса.
Обновление: вы исправили свой заголовок, поэтому игнорируйте остальные ...
Теперь о вашем названии: Что касается LINQ, IEnumerable и IQueryable очень похожи. Они оба имеют почти одинаковые методы расширения (Select, Where, Count и т. Д.), С основным (только?) Различием в том, что IEnumerable принимает Func<TIn,TOut>
в качестве параметров, а IQueryable принимает Expression<Func<TIn,TOut>>
в качестве параметров. Вы выражаете оба одинаково (обычно выражения lamba), но внутренне они совершенно разные.
IEnumerable - это дверь в LINQ to Objects. Методы расширения LINQ to Objects можно вызывать для любого IEnumerable (массивы, списки, все, что вы можете перебрать с помощью foreach
), а Func<TIn,TOut>
преобразуется в IL во время компиляции и выполняется как обычный код метода во время выполнения. Обратите внимание, что некоторые другие поставщики LINQ используют IEnumerable и поэтому на самом деле используют LINQ to Objects (LINQ to XML, LINQ to DataSet).
IQueryable используется LINQ to SQL, LINQ to Entities и другими поставщиками LINQ, которым необходимо проанализировать ваш запрос и перевести его, а не выполнять ваш код напрямую. Запросы IQueryable и их Expression<Func<TIn,TOut>>
не компилируются в IL во время компиляции. Вместо этого создается дерево выражений , которое можно просмотреть во время выполнения. Это позволяет переводить операторы на другие языки запросов (например, T-SQL). Дерево выражений может быть скомпилировано в Func во время выполнения и выполнено при желании.
Пример, иллюстрирующий эту разницу, можно найти в этом вопросе , где OP хочет выполнить часть запроса LINQ to SQL в SQL Server, перенести объекты в управляемый код и выполнить остальную часть запрос в LINQ to Objects. Чтобы достичь этого, все, что ему нужно сделать, это привести IQueryable в IEnumerable, где он хочет, чтобы произошел переход.