C# - Usando a palavra reservada 'yield' (revisitado)

 Neste artigo vou apresentar os conceitos e mostrar como usar a palavra reservada yield da linguagem C#.


Você já ouviu falar da palavra reservada 'yield' ?

E se já ouviu ou conhece o 'yield' você já o utilizou alguma vez em seu código ?

Sabia que este recurso existe desde a versão 2.0 da linguagem C# ?

Qual o motivo de não usar o recurso 'yield' ?

Diante de tantas perguntas vamos começar apresentando o conceito sobre o 'yield' para saber pra que ele serve.

O guia de referência da linguagem C# diz o seguinte sobre o yield:

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.

Dizendo em outras palavras:   "Podemos usar yield para evitar a criação de coleções temporárias que são muito comuns em métodos que retornam uma lista."

Este é um bom motivo para você passar a usar o recurso yield em seu código.  Vejamos um exemplo prático:

1 - Exemplo onde temos um método Teste() que percorre uma lista de animais e exibe os animais com mais de 5 letras e retorna um IEnumerable:

using System;
using System.Collections.Generic;
namespace Cshp_yield
{
    class Program
    {
        static List<string> Animais = new List<string> { "Cavalo", "Águia","Elefante", "Girafa", "Tigre" };
        static void Main(string[] args)
        {
            IEnumerable<string> resultado = Teste();
            foreach(var nome in resultado)
            {
                Console.WriteLine(nome);
            }
            Console.ReadKey();
        }
        static IEnumerable<string> Teste()
        {
            List<string> temp = new List<string>();
            foreach (var data in Animais)
            {
                if (data.Length > 5)
                {
                    temp.Add(data);
                }
            }
            return temp;
        }
    }  
}

Observe que tivemos que criar uma variável temporária temp do tipo List<string> para receber os valores obtidos a partir da lista de animais:  List<string> temp = new List<string>();

2 -  A seguir vemos o mesmo exemplo usando a palavra reservada 'yield' :

using System;
using System.Collections.Generic;
namespace Cshp_yield
{
    class Program
    {
        static List<string> Animais = new List<string> { "Cavalo", "Águia","Elefante", "Girafa", "Tigre" };
        static void Main(string[] args)
        {
            IEnumerable<string> resultado = Teste();
            foreach(var nome in resultado)
            {
                Console.WriteLine(nome);
            }
            Console.ReadKey();
        }
        static IEnumerable<string> Teste()
        {
            foreach (var data in Animais)
            {
                if (data.Length > 5)
                {
                    yield return data;
                }
            }
        }
    }  
}

Neste código não precisamos definir uma lista de string temporária para obter o resultado pois a instrução yield return retorna os resultados.

IEnumerable é uma interface e descreve um tipo que implementa métodos internos requeridos pela utilização de laços foreach e o Return usado com o Yield é parecido com o return, seguido por um 'goto' para a instrução yield na próxima interação do laço foreach.

Creio que é um bom motivo para usar o yield. Não é mesmo ???

Pegue o projeto completo aqui : Cshp_yield.zip

Considerai os corvos, que nem semeiam, nem segam, nem têm despensa nem celeiro, e Deus os alimenta; quanto mais valeis vós do que as aves? Lucas 12:24

Referências:


José Carlos Macoratti