C# -  Para que serve a palavra reservada yield ?


 Neste artigo vou apresentar os conceitos relacionados com a palavra reservada yield da linguagem C#.

Se você tiver a curiosidade de ver qual a tradução da palavra yield para o português vai encontrar as seguintes definições : rendimento, produção, potência, vazão, ganho, retorno, etc.

Consultando a referência da linguagem C# temos que :

"Quando você usa a palavra-chave yield em uma instrução, você indica que o método, o operador ou o acessador get em que ela é exibida é um iterador. Usar yield para definir um iterador elimina a necessidade de uma classe adicional explícita (a classe que mantém o estado de uma enumeração, consulte IEnumerator<T> para obter um exemplo) ao implementar o padrão IEnumerable e IEnumerator para um tipo de coleção personalizado."

O exemplo a seguir mostra as duas formas de instrução yield.

-  Você usa uma instrução yield return para retornar cada elemento individualmente.
 - Você pode usar uma instrução yield break para terminar a iteração.

Você não pode incluir uma instrução yield return ou yield break nos métodos com as seguintes características:

Verifique as seguintes restrições quanto ao tratamento de exceções usando yield:

Da teoria à prática

Em geral, usamos a palavra reservada yield em métodos que retornam o tipo IEnumerable ou IEnumerable<T>.

Vejamos um exemplo bem simples: (adaptado do site: yield (Referência de C#) - MSDN - Microsoft )

No código à direita estamos usando a palavra reservada yield para retornar o valor do método Potencia() que é do tipo IEnumerable.

No código à esquerda removemos o yield e obtemos duas exceções  conforme mostra a imagem:

using System;
using System.Collections.Generic;
namespace Cshp_yield
{
    class Program
    {
        static void Main(string[] args)
        {
            // Exibe a potência de 2 elevado ao expoente 8
            foreach (int i in Potencia(2, 8))
            {
                Console.Write("{0} ", i);
            }
            Console.ReadKey();
        }
        public static IEnumerable<int> Potencia(int numero, int exponente)
        {
            int resultado = 1;
            for (int i = 0; i < exponente; i++)
            {
                resultado = resultado * numero;
                yield return resultado;
            }
        }
    }
}

 

 
 

No código temos uma instrução yield return dentro de um loop foreach onde cada iteração do corpo da instrução cria uma chamada ao método Potencia.

Cada chamada ao método prossegue para a próxima execução da instrução yield return que ocorre durante a próxima iteração do loop foreach.

O tipo de retorno do método iterador é IEnumerable que é um tipo de interface de iterador. Quando o método iterador é chamado, ele retorna um objeto enumerável que contém as potências de um número.

Assim, yield return é semelhante a uma declaração return (que passa o controle do fluxo método de chamada), seguido de um "goto" para a declaração yield na próxima iteração do foreach.

Podemos então usar o yield para gerar um Enumerable de qualquer coisa como por exemplo gerar um coleção de números inteiros:

    class Program
    {
        static void Main(string[] args)
        {
            var numeros = Numeros(0, 10);
            foreach(int num in numeros)
            {
                Console.WriteLine(num);
            }
            Console.ReadKey();
        }
        public static IEnumerable<int> Numeros(int inicio, int fim)
        {
            for (int i = inicio; i <= fim; i++)
                yield return i;
        }
     }
 
 

Ou retornar um Enumerable de strings :

    class Program
    {
        static void Main(string[] args)
        {
             var palavras = ConverteParaCaixaBaixa("Macoratti .net, quase tudo para .Net");    
            foreach (string pal in palavras)
            {
                Console.Write("{0} ", pal)  ;
           }
       }
           public static IEnumerable<string> ConverteParaCaixaBaixa(string frase)
        {
            foreach (var palavra in frase.Split(' '))
            {
                yield return palavra.ToLower();
            }
        }
     }
 
 

Assim, creio que você já sacou para que serve e como deve usar o yield.

E estamos conversados...

"Se alguém me serve, siga-me, e onde eu estiver, ali estará também o meu servo. E, se alguém me servir, meu Pai o honrará. "
João 12:26

 

Referências:


José Carlos Macoratti