Domine o yield em C#: iteração sob demanda e eficiência de memória

Em aplicações que lidam com grandes volumes de dados, pode ser necessário começar a retornar resultados antes que todo o processamento seja concluído. Isso é especialmente útil para evitar o consumo excessivo de memória e melhorar o desempenho da aplicação. No C#, a palavra-chave “yield” é uma ferramenta bastante útil para lidar com essa necessidade, permitindo a criação de iteradores que geram valores sob demanda. Neste artigo exploraremos como “yield return” e “yield break” funcionam, sua aplicação prática e os benefícios no gerenciamento de coleções grandes.

O que é yield?

Em C#, “yield” é usado dentro de métodos iteradores para retornar elementos um por um, sem precisar armazenar todos os itens na memória. A palavra-chave “yield return” permite que um método produza uma sequência de valores sob demanda, enquanto “yield break” encerra a iteração antecipadamente.

Como yield funciona internamente em métodos iteradores

Quando um método contém “yield return”, o compilador gera automaticamente um iterador que preserva o estado entre as chamadas subsequentes. Isso significa que os valores são calculados sob demanda, permitindo uma iteração eficiente em memória.

yield return

Para entendermos melhor vamos ver um exemplo prático:

				
					foreach (var numero in GeradorNumeros(5))
{
    Console.WriteLine(numero);
}

IEnumerable<int> GeradorNumeros(int quantidade)
{
    for (int i = 1; i <= quantidade; i++)
    {
        yield return i;
    }
}

				
			

No código acima foi criado o método “GeradorNumeros”, que recebe um número inteiro “quantidade” e retorna uma sequência de números de 1 até a quantidade informada. Dentro do “for”, cada valor de “i” é retornado usando “yield return i;”, o que significa que o método pausa a execução e retorna o valor atual.

O “foreach” percorre essa sequência e imprime cada número no console. A cada iteração, o método “GeradorNumeros” continua de onde parou, sem recriar a sequência.

yield break

O “yield break” interrompe a execução do iterador imediatamente, encerrando a iteração sem retornar mais elementos. Isso é útil quando uma condição específica determina que a sequência deve ser interrompida.

				
					foreach (var numero in GeradorNumeroComBreak(5))
{
    Console.WriteLine(numero);
}

IEnumerable<int> GeradorNumeroComBreak(int maximo)
{
    for (int i = 1; i <= maximo; i++)
    {
        if (i == 4)
            yield break;
        yield return i;
    }
}

				
			

O método “GeradorNumeroComBreak” gera uma sequência de números de “1” até “maximo”. O “for” itera os números e retorna cada um deles usando “yield return”. Quando “i” atinge o valor 4, “yield break” é chamado, encerrando a iteração imediatamente. O resultado da iteração será a exibição dos números 1, 2 e 3, pois a execução será interrompida antes de retornar o número 4.

Acelere a sua carreira conosco!

Se você é Desenvolvedor .NET Júnior e quer acelerar sua carreira até nível Pleno com salário de R$7k+, ou mesmo busca a primeira vaga, conheça a Mentoria .NET StartClique aqui

Se é Desenvolvedor .NET Pleno ou Sênior e quer virar referência técnica em sua equipe e mercado, com salário de R$10k+, conheça a Mentoria .NET ExpertClique aqui

Vantagens e desvantagens do uso de yield

Vantagens:

  • Reduz o uso de memória ao gerar elementos sob demanda.
  • Facilita a implementação de iteradores complexos.
  • Melhora a eficiência ao processar coleções grandes.
  • Evita a necessidade de criar listas intermediárias.

 

Desvantagens:

  • Pode ser menos eficiente quando todos os elementos precisam ser armazenados na memória.
  • Difícil depurar devido ao comportamento lazy.
  • Métodos iteradores não podem ter parâmetros ref ou out.

Conclusão

O uso do yield no C# permite criar iteradores eficientes e evitar o consumo excessivo de memória. Ao utilizar yield, você pode otimizar a iteração de grandes coleções e sequências dinâmicas de forma simples e elegante. Experimente aplicar yield em seus projetos para melhorar a eficiência e a legibilidade do seu código!