Expressão fluente e de consulta - existe algum benefício de um sobre o outro?


255

O LINQ é uma das maiores melhorias no .NET desde os genéricos e economiza muito tempo e linhas de código. No entanto, a sintaxe fluente parece vir muito mais natural para mim do que a sintaxe da expressão de consulta.

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();

Existe alguma diferença entre os dois ou existe algum benefício particular de um sobre o outro?


1
Para consultas complexas, acho a sintaxe lambda mais compreensível / legível, mas a sintaxe da consulta é simplesmente mais bonita.
Nawfal 1/08/15

Respostas:


255

Nem é melhor: eles atendem a diferentes necessidades. A sintaxe da consulta é própria quando você deseja aproveitar várias variáveis ​​de intervalo . Isso acontece em três situações:

  • Ao usar a palavra-chave let
  • Quando você possui vários geradores ( de cláusulas)
  • Ao fazer junções

Aqui está um exemplo (dos exemplos do 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;

Agora compare isso com a mesma coisa na sintaxe do método:

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);

A sintaxe do método, por outro lado, expõe toda a gama de operadores de consulta e é mais concisa com consultas simples. Você pode obter o melhor dos dois mundos misturando sintaxe de consulta e método. Isso geralmente é feito em consultas 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
Boa resposta. Você pode me contar um pouco mais sobre o que ".Selecione (nome => novo {nome, fName})" está fazendo?
quillbreaker

12
Ele seleciona a palavra individual (anne, williams, john, etc) junto com o nome completo em um tipo anônimo. Isso permite que você "carregue" o nome completo original para ter acesso ao nome completo e à palavra individual no restante da consulta.
91110 Joe Albahari

58

Prefiro usar o último (às vezes chamado de "sintaxe de compreensão de consulta") quando posso escrever toda a expressão dessa maneira.

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

var title = titlesQuery.FirstOrDefault();

Assim que eu tiver que adicionar (parênteses) e .MethodCalls(), eu mudo.

Quando uso o primeiro, costumo colocar uma cláusula por linha, como esta:

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

Acho isso um pouco mais fácil de ler.


29

Cada estilo tem seus prós e contras. A sintaxe da consulta é mais agradável quando se trata de junções e possui a útil palavra-chave let, que facilita a criação de variáveis ​​temporárias dentro de uma consulta.

A sintaxe fluente, por outro lado, tem muito mais métodos e operações que não são expostos pela sintaxe da consulta. Além disso, como são apenas métodos de extensão, você pode escrever o seu próprio.

Descobri que toda vez que começo a escrever uma instrução LINQ usando a sintaxe da consulta, acabo tendo que colocá-la entre parênteses e voltar a usar métodos de extensão LINQ fluentes. A sintaxe da consulta simplesmente não possui recursos suficientes para usar por si só.


"Como são apenas métodos de extensão, você pode escrever o seu." - você enfrentaria esse problema? stackoverflow.com/a/3850254/1175496
The Red Pea

20

No VB.NET, prefiro a sintaxe da consulta.

Detesto repetir a feia Functionpalavra-chave:

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)

Esta consulta pura é muito mais legível e sustentável na minha opinião:

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

A sintaxe de consulta do VB.NET também é mais poderosa e menos detalhada do que em C #: https://stackoverflow.com/a/6515130/284240

Por exemplo, esta consulta 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
Minha simpatia pelos desenvolvedores de VB que não podem usar o estilo de consulta.
Nawfal

1
Seu último exemplo de C # é muito simplista para ser valioso: você simplesmente escreveria `dataTable1.AsEnumerable (). Take (10);
Emyr

@ Emyr: meu último parágrafo, que começa com "a sintaxe de consulta do VB.NET também é mais poderosa e menos detalhada do que em C #", está apenas comparando a sintaxe de consulta do VB.NET com o C #, você está usando a sintaxe do método.
Tim Schmelter

15

Não recebo a sintaxe da consulta. Não há razão para isso em minha mente. let pode ser obtido com os tipos .Select e anônimo. Eu só acho que as coisas parecem muito mais organizadas com a "pontuação" lá dentro.


9
Várias associações podem ficar bastante trabalhosas rapidamente com a sintaxe fluente. No entanto, geralmente uso-me fluentemente - a menos que haja junções.
Roman Starkov

1
@ Hunter Instance: O mesmo aqui. Levei um bom tempo para começar a entender a idéia de sintaxe fluente. Em combinação com o poderoso enumerável e a idéia de funções "puras", agora eu realmente aprecio isso, e anteriormente situações complicadas que não tinham uma boa representação de código. Para ye-ole-SQL-parte do cérebro, ainda é uma benção ter sintaxe de consulta.
Xan-Kun Clark-Davis

13

A interface fluente, se houver apenas um onde. Se eu precisar de uma seleção ou pedido, geralmente uso a sintaxe de consulta.


8

A sintaxe fluente parece realmente mais poderosa, mas também deve funcionar melhor para organizar o código em pequenos métodos reutilizáveis.


5

Eu sei que esta pergunta está marcada com c #, mas a sintaxe fluente é dolorosamente detalhada com o VB.NET.


4

Gosto muito da sintaxe Fluente e tento usá-la onde posso, mas em alguns casos, por exemplo, onde uso junções, geralmente prefiro a sintaxe Query; nesses casos, acho mais fácil ler e acho que algumas pessoas são mais familiares à sintaxe de consulta (semelhante a SQL) do que lambdas.


4

Embora eu compreenda e goste do formato fluente, permaneci no Query por motivos de legibilidade. As pessoas que estão sendo introduzidas no LINQ acharão o Query muito mais confortável de ler.


4

Eu prefiro a sintaxe da consulta, pois vim da programação tradicional da Web usando SQL. É muito mais fácil para mim envolver minha cabeça. No entanto, acho que vou começar a utilizar o .Where (lambda), pois é definitivamente muito mais curto.


4

Estou usando o Linq há cerca de 6 meses. Quando comecei a usá-lo, preferi a sintaxe da consulta, pois ela é muito semelhante ao T-SQL.

Mas agora estou gradualmente voltando ao primeiro, pois é fácil escrever trechos reutilizáveis ​​de código como métodos de extensão e apenas encadear eles. Embora eu ache que colocar cada cláusula em sua própria linha ajuda muito na legibilidade.


3

Acabei de configurar os padrões da nossa empresa e aplicamos o uso dos métodos de extensão. Eu acho que é uma boa ideia escolher um sobre o outro e não misturá-los no código. Os métodos de extensão são mais parecidos com o outro código.

A sintaxe de compreensão não tem todos os operadores e usa parênteses em torno da consulta e adiciona métodos de extensão, afinal me implora por usar métodos de extensão desde o início.

Mas, na maioria das vezes, é apenas uma preferência pessoal, com algumas exceções.


3
Não aplicarei preferências pessoais. Mas sou eu.
Memet Olsen 23/03
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.