Свободное выражение и выражение запроса - есть ли какие-либо преимущества одного над другим?

255

LINQ - это одно из величайших улучшений .NET, так как оно дженериков и экономит массу времени и строк кода. Однако свободный синтаксис кажется мне гораздо более естественным, чем синтаксис выражения запроса.

var title = entries.Where(e => e.Approved)
    .OrderBy(e => e.Rating).Select(e => e.Title)
    .FirstOrDefault();

var query = (from e in entries
             where e.Approved
             orderby e.Rating
             select e.Title).FirstOrDefault();

Есть ли разница между этими двумя или есть какое-то конкретное преимущество одного над другим?

JarrettV
источник
1
Для сложных запросов я нахожу лямбда-синтаксис более понятным / читабельным, но синтаксис запросов просто красивее.
Nawfal

Ответы:

255

Ни то, ни другое лучше: они служат различным потребностям. Синтаксис запроса вступает в свои права, когда вы хотите использовать несколько переменных диапазона . Это происходит в трех ситуациях:

  • При использовании ключевого слова let
  • Когда у вас есть несколько генераторов ( из пунктов)
  • При выполнении объединений

Вот пример (из примеров LINQPad):

string[] fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" };

var query =
  from fullName in fullNames
  from name in fullName.Split()
  orderby fullName, name
  select name + " came from " + fullName;

Теперь сравните это с синтаксисом метода:

var query = fullNames
  .SelectMany (fName => fName.Split().Select (name => new { name, fName } ))
  .OrderBy (x => x.fName)
  .ThenBy  (x => x.name)
  .Select  (x => x.name + " came from " + x.fName);

Синтаксис метода, с другой стороны, предоставляет полную гамму операторов запросов и более лаконичен с простыми запросами. Вы можете получить лучшее из обоих миров, смешав синтаксис запроса и метода. Это часто делается в запросах LINQ to SQL:

var query =
  from c in db.Customers
  let totalSpend = c.Purchases.Sum (p => p.Price)    // Method syntax here
  where totalSpend > 1000
  from p in c.Purchases
  select new { p.Description, totalSpend, c.Address.State };
Джо Албахари
источник
2
Хороший ответ. Можете ли вы рассказать мне немного больше о том, что делает ".Select (name => new {name, fName})"?
quillbreaker
12
Он выбирает отдельное слово (anne, williams, john и т. Д.) Вместе с полным именем в анонимном виде. Это позволяет вам «нести» исходное полное имя, чтобы иметь доступ как к полному имени, так и к отдельному слову в остальной части запроса.
Джо Албахари
58

Я предпочитаю использовать последний (иногда называемый «синтаксис понимания запроса»), когда я могу написать все выражение таким образом.

var titlesQuery = from e in entries
                  where e.Approved
                  orderby e.Rating
                  select e.Titles;

var title = titlesQuery.FirstOrDefault();

Как только я должен добавить (скобки) и .MethodCalls()я меняю.

Когда я использую первое, я обычно помещаю одно предложение в строку, например так:

var title = entries
    .Where (e => e.Approved)
    .OrderBy (e => e.Rating)
    .Select (e => e.Title)
    .FirstOrDefault();

Я считаю, что это немного легче читать.

Джей Базузи
источник
29

У каждого стиля есть свои плюсы и минусы. Синтаксис запроса более приятен, когда речь идет о соединениях, и имеет полезное ключевое слово let, которое облегчает создание временных переменных внутри запроса.

Свободный синтаксис, с другой стороны, имеет гораздо больше методов и операций, которые не отображаются в синтаксисе запроса. Кроме того, поскольку они являются просто методами расширения, вы можете написать свой собственный.

Я обнаружил, что каждый раз, когда я начинаю писать оператор LINQ с использованием синтаксиса запроса, мне приходится заключать его в скобки и возвращаться к использованию беглых методов расширения LINQ. Синтаксис запроса просто не имеет достаточно функций для использования сам по себе.

Джеймс Ньютон-Кинг
источник
«поскольку они являются просто методами расширения, вы можете написать свой собственный». - Вы столкнетесь с этой проблемой? stackoverflow.com/a/3850254/1175496
Красный горошек
20

В VB.NET я очень предпочитаю синтаксис запросов.

Ненавижу повторять уродливое Functionключевое слово:

Dim fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" };
Dim query =
     fullNames.SelectMany(Function(fName) fName.Split().
     Select(Function(Name) New With {Name, fName})).
     OrderBy(Function(x) x.fName).
     ThenBy(Function(x) x.Name).
     Select(Function(x) x.Name & " came from " & x.fName)

Этот аккуратный запрос, на мой взгляд, гораздо более читабелен и понятен:

query = From fullName In fullNames
        From name In fullName.Split()
        Order By fullName, name
        Select name & " came from " & fullName

Синтаксис запросов в VB.NET также более мощный и менее подробный, чем в C #: https://stackoverflow.com/a/6515130/284240

Например, этот запрос LINQ to DataSet (Objects)

VB.NET:

Dim first10Rows = From r In dataTable1 Take 10

C #:

var first10Rows = (from r in dataTable1.AsEnumerable() 
                   select r)
                   .Take(10);
Тим Шмельтер
источник
9
Мои симпатии тем разработчикам VB, которые не могут использовать стиль запросов.
nawfal
1
Ваш последний пример C # слишком упрощен, чтобы быть полезным: вы просто написали бы `dataTable1.AsEnumerable (). Take (10);
Эмир
@Emyr: мой последний абзац, который начинается с «Синтаксис запроса VB.NET также более мощный и менее многословный, чем в C #», просто сравнивает синтаксис запроса VB.NET с C #, вы используете синтаксис метода.
Тим Шмелтер
15

Я не понимаю синтаксис запроса вообще. У меня просто нет причин для этого. let может быть достигнут с .Select и анонимными типами. Я просто думаю, что все выглядит намного более организованным с «пунктуацией».

Охотник за экземплярами
источник
9
Многократные объединения могут стать довольно трудоемкими довольно быстро с беглым синтаксисом. Я обычно использую свободно, хотя - если не участвуют объединения.
Роман Старков
1
@ Instance Hunter: То же самое здесь. Мне потребовалось много времени, чтобы начать понимать идею свободного синтаксиса. В сочетании с мощным перечислимым и идеей «чистых» функций мне теперь очень нравится это, и ранее сложные ситуации, которые не имели красивого представления кода. Для ye-ole-SQL-части мозга это все-таки благословение иметь синтаксис запроса.
Ксан-Кун Кларк-Дэвис
13

Свободный интерфейс, если есть только где. Если мне нужно выбрать или заказать, я обычно использую синтаксис запроса.

Джеймс Керран
источник
8

Свободный синтаксис действительно кажется более мощным, он также должен работать лучше для организации кода в небольшие многократно используемые методы.

Kozyarchuk
источник
5

Я знаю, что этот вопрос помечен C #, но синтаксис Fluent мучительно многословен с VB.NET.

Larsenal
источник
4

Мне действительно нравится синтаксис Fluent, и я стараюсь использовать его там, где могу, но в некоторых случаях, например, когда я использую объединения, я обычно предпочитаю синтаксис запроса, в таких случаях мне легче читать, и я думаю, что некоторые люди Query (SQL-подобный) синтаксис более знаком, чем лямбды.

CMS
источник
4

Несмотря на то, что я понимаю и мне нравится свободный формат, я пока придерживался Query для удобства чтения. Люди, только знакомящиеся с LINQ, найдут Query намного удобнее для чтения.

LizB
источник
4

Я предпочитаю синтаксис запроса, поскольку я пришел из традиционного веб-программирования с использованием SQL. Мне намного легче обернуть голову. Тем не менее, я думаю, что я начну использовать .Where (лямбда), поскольку он определенно намного короче.

Стив Транби
источник
4

Я использую Linq около 6 месяцев. Когда я впервые начал использовать его, я предпочел синтаксис запроса, так как он очень похож на T-SQL.

Но теперь я постепенно перехожу к первому, так как легко написать повторно используемые куски кода в качестве методов расширения и просто связать их вместе. Хотя я считаю, что размещение каждого предложения в отдельной строке очень помогает с удобочитаемостью.

Энтони Скотт
источник
3

Я только что установил стандарты нашей компании, и мы применяем методы расширения. Я думаю, что это хорошая идея, чтобы выбрать один из других, а не смешивать их в коде. Методы расширения читать больше, как и другой код.

Синтаксис понимания не имеет всех операторов и использует круглые скобки вокруг запроса и добавляет методы расширения, в конце концов, просто просит меня использовать методы расширения с самого начала.

Но по большей части это всего лишь личные предпочтения с несколькими исключениями.

Rodi
источник
3
Я не буду навязывать свои личные предпочтения. Но это я.
Мемет Олсен