Boas Galera!
Vou falar um pouco sobre o “yield“, ele nem sempre é lembrado pelos desenvolvedores, mas está disponível desde a versão 2.0 do C#.
Sucintamente, o operador “yield“ faz iterações através de objetos retornados por um método, guardando o estado atual do objeto via IL(Intermediate Language), sendo assim, não é necessário manter o estado via código.
Neste contexto temos o “yield return“ para retornar cada elemento da iteração individualmente e o “yield break” que serve para terminar a iteração.
Alguns detalhes sobre esse cara:
- O tipo de retorno deve ser um IEnumerable, IEnumerable<T>, IEnumerator ou IEnumerator<T>;
- A instrução não pode conter quaisquer parâmetros ref ou out;
- Você não pode usar uma instrução yield return ou yield break nos seguintes casos:
- yield return não pode ser utilizado em um bloco try-catch; Mas pode ser utilizado em um bloco try em uma instrução try-finally;
- yield break pode estar localizada em um bloco try ou em um bloco catch, mas não em um bloco finally.
“Legal, mas qual a vantagem de usar isso?”. Simples, performance! 😀 Além da praticidade, ele deixa o processo de iteração muito mais rápido, só temos que tomar alguns cuidados.
Se eu preciso apenas recuperar os dados e exibir na tela, como exemplo, recuperar dados de um banco de dados e exibir em um grid, o yield é altamente recomendável, mas se eu preciso manipular esses dados de alguma forma, seu uso não é recomendável, podemos observar que com apenas um .ToList() há uma perda muito grande de performance, veja no exemplo:
Aqui, podemos ver um exemplo, de uma lista de 10.000.000 de itens sendo preenchidos com yield e sem o yield. Ao fazer uso de cada um destes métodos, o resultado é bastante interessante, veja:
O yield trouxe os registros ignorantemente rápido, 4 segundos de diferença com a outra iteração, mas veja bem que o simples fato de adicionarmos o .ToList() no método, já não fica tão legal.
E porquê ele fica tão lento quando o .ToList() é usado? O motivo da demora não é culpa do yield e sim da conversão de IEnumerable para IList; como sabemos, o IList herda de IEnumerable, e possui bem mais recursos, como acessar um item por índice, por exemplo, e esse tempo a mais é a preparação para a manipulação dos dados
Pois então, use-o, mas com responsabilidade!
O código de exemplo do yield está disponível no github pra quem quiser dar uma olhada: https://github.com/vmussak/YieldExample
Por hoje é só isso, qualquer dúvida ou sugestão, estou à disposição!
Referências: