C# yield: tutorial passo a passo sobre coleções preguiçosas

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que você precisa de yield em C#? O segredo das coleções preguiçosas



Imagine: você está escrevendo um método que deve retornar uma lista de números de 1 a um milhão. A primeira coisa que vem à mente é criar um List<int>, preenchê-lo e retorná-lo. Mas e se o código chamador quiser apenas os primeiros 10 elementos? Você ainda gastou tempo criando um milhão de objetos, ocupou memória — e tudo em vão.



É aqui que entra a palavra-chave yield em C#. Não é apenas açúcar sintático, mas uma ferramenta poderosa para criar sequências preguiçosas (lazy). Neste artigo, vamos analisar yield return e yield break com exemplos reais, entender como funcionam internamente e aprender a aplicá-los no desenvolvimento do dia a dia.



Este tutorial é baseado em uma pergunta real do Stack Overflow que reuniu milhares de visualizações. Nós o adaptamos para conteúdo educacional, adicionando exemplos passo a passo de código C# e dicas práticas úteis.



O que é yield em C#? Em palavras simples



yield é uma palavra-chave contextual em C# que informa ao compilador: "Este método é um iterador". Quando você escreve yield return, o método não executa tudo de uma vez. Em vez disso, ele retorna os elementos um por um, conforme solicitados pelo código chamador. Isso é chamado de execução preguiçosa.



Ao contrário do return comum, que encerra o método, yield return pausa o método, salva seu estado e retorna o elemento atual. Na próxima chamada, o método continua de onde parou.



Sintaxe: yield return e yield break



Em C#, existem duas formas de yield:



  • yield return — retorna o próximo elemento da sequência.
  • yield break — encerra imediatamente a iteração (como break em um loop).


O método que usa yield deve retornar um destes tipos:

  • IEnumerable<T>
  • IEnumerable
  • IAsyncEnumerable<T> (a partir do C# 8.0)
  • IEnumerator<T> ou IEnumerator


Primeiro exemplo: do simples ao complexo



Vamos escrever um iterador simples que gera números de 1 a 5:



public static IEnumerable<int> GetNumbers(){    yield return 1;    yield return 2;    yield return 3;    yield return 4;    yield return 5;}

// Uso:foreach (int number in GetNumbers()){ Console.WriteLine(number);}


Saída:

12345


À primeira vista, parece uma lista comum. Mas a diferença é enorme: cada elemento é gerado apenas quando solicitado pelo foreach. Nenhuma alocação de memória para a lista inteira!



Como funciona internamente?



O compilador C# transforma o método com yield em uma máquina de estados (state machine) completa. Ele cria uma classe que implementa IEnumerable<T> e IEnumerator<T>. Essa classe armazena:

  • O estado atual (em qual linha do método paramos).
  • As variáveis locais do método.
  • Uma referência ao objeto atual (this), se o método não for estático.


Cada vez que MoveNext() é chamado (e isso é feito pelo foreach), a máquina de estados retoma a execução de onde parou.



Exemplo real: leitura de um arquivo grande



Imagine que você precisa processar um arquivo de log de 10 GB. Se você ler tudo na memória, o programa falhará com OutOfMemoryException. Com yield, você pode ler o arquivo linha por linha e processar cada linha em tempo real:



public static IEnumerable<s                

Blogs

Book Recommendations