Você ainda não é assinante?

Escreva códigos efetivos!

Desde a sua versão 3.0, a adição do recurso do LINQ (Language Integrated Query) no C# mudou para sempre a forma como seus desenvolvedores manipulam e pesquisam listas e coleções.

Olhando pro código Foi vc que escreveu? Linq Verdade

Quando migramos de outras linguagens para o C# nos sentimos tentados a interagir com estruturas de dados através de laços de repetição, como whileou for. Como esses são recursos da linguagem, isso é plenamente aceitável, claro.

Contudo, se você está no C# e está usando laços de repetição para iterar coleções e listas, provavelmente está deixando de usar o LINQ quando deveria! Veja o código abaixo, por exemplo:

  using EffectiveCSharp.DeclarativeVsImperative.DAO;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  

  namespace EffectiveCSharp.DeclarativeVsImperative
  {
      class Program
      {
          static void Main(string[] args)
          {
              BoletoDAO dao = new BoletoDAO();
              IList<Boleto> boletos = dao.getBoletosParaPagamento();
              ValidarVencimentoBoleto validar = new ValidarVencimentoBoleto();
          }
      }
  }

Na linha 14, instanciamos um objeto BoletoDAO e na linha 15 atribuímos o resultado do método getBoletosVencidos a um objeto do tipo IList. Este resultado foi gerado dinamicamente pelo método, mas poderia ser uma coleção oriunda de um banco de dados.

Em seguida, na linha 16 instanciamos um objeto ValidarVencimentoBoleto. Uma classe simples de validação que verificará se um boleto está vencido. Desta forma podemos iterar por esta lista e fazer a verificação se o boleto está vencido para, então, somarmos somente os valores dos boletos que se encontram vencidos.

Verifique o código abaixo onde fazemos a iteração pela lista utilizando o laço de repetição foreach:

  18 double soma = 0;
  19 
  20 foreach(Boleto boleto in boletos)
  21 {
  22           if(validar.isVencido(boleto))
  23           {
  24                           soma += boleto.Valor;
  25           }
  26 }
  27 Console.WriteLine(soma);
  28 Console.ReadLine();

Na linha 18 iniciamos uma variável do tipo double, soma. Na linha 20 iniciamos o foreach iterando pela listagem contendo um if para verificar se o boleto está vencido utilizando o método isVencido para isso.

Esta solução de oito linhas de código é válida, mas sua leitura não está tão clara e concisa quanto poderia ser. Veja, então o seguinte código:

  18 double soma = (from boleto in boletos
  19   where validar.isVencido(boleto) == true
  20   select boleto.Valor).Sum();
  21
  22 Console.WriteLine(soma);
  23 Console.ReadLine();

Mais simples, não? Na linha 18 iniciamos a mesma variável soma, do tipo double. E em seu valor atribuímos uma expressão LINQ utilizando a sintaxe de query. Aqueles já familiarizados com SQL não terão dificuldade de interpretar este código. As únicas diferenças estão no posicionamento do select, que aqui vai para o final da expressão, e no método Sum(), que é um dos métodos de extensão disponíveis pelo LINQ.

Que tal simplificar ainda mais este código em uma linha só?

18  double soma = boletos.Where(b => validar.isVencido(b)).Sum(b => b.Valor);

Se você preferir, o LINQ também oferece a sintaxe fluente, como visto acima. Mais uma vez, métodos de extensão são utilizados. Primeiramente aplicamos um filtro Where, que recebe uma expressão lambda para verificar o vencimento de um boleto b, e o Sum, que também recebe uma expressão que identifica qual é a propriedade que pretendemos somar.

Mesmo que este exemplo seja simples, podemos ver que com o LINQ o volume de código escrito é bem reduzido.

Com isso temos um código mais limpo e legível. Quanto menos código, menos possibilidades de bugs serem introduzidos em nossa programação.

Sempre considere utilizar o LINQ para iterar e manipular suas listas. Ele será um grande aliado do desenvolvedor C# para tarefas como esta, sejam as listas vindas ou não de um banco de dados.

Nota sobre performance: Tenha em mente que, em termos de performance, nem sempre o LINQ será mais eficaz, pois dependerá muito da forma como será utilizado e das características do negócio do código escrito. Em cenários onde a questão da performance é crítica, não se esqueça de testar os dois métodos para verificar o que seria mais adequado em seu caso.

Sugestão de conteúdo

Guias de consulta