Share via


yield (Referência de C#)

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 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.

yield return <expression>;
yield break;

Comentários

Você usa uma instrução yield return para retornar cada elemento individualmente.

Você consome um método iterador ao usar uma instrução foreach ou consulta LINQ. Cada iteração do loop foreach chama o método iterador. Quando uma instrução yield return é atingida no método iterador, expression é retornado e o local atual no código é retido. A execução será reiniciada desse local na próxima vez que a função iteradora for chamada.

Você pode usar uma instrução yield break para terminar a iteração.

Para obter mais informações sobre iteradores, consulte Iteradores (C# e Visual Basic).

Métodos de Iterador Acessadores get

A declaração de um iterador deve atender aos seguintes requisitos:

O tipo yield de um iterador que retorna IEnumerable ou IEnumerator é object. Se o iterador retornar IEnumerable ou IEnumerator, uma conversão implícita deverá existir do tipo da expressão na instrução yield return para o parâmetro de tipo genérico.

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

Tratamento de exceções

Uma instrução yield return não pode estar localizada em um bloco try-catch. Uma instrução yield return pode estar localizada no bloco try de uma instrução try-finally.

Uma instrução yield break pode estar localizada em um bloco try ou em um bloco catch, mas não em um bloco finally.

Se o corpo foreach (fora do método iterador) acionar uma exceção, um bloco finally no método iterador será executado.

Implementação Técnica

O código a seguir retorna uma IEnumerable<string> de um método iterador e itera através de seus elementos.

IEnumerable<string> elements = MyIteratorMethod();
foreach (string element in elements)
{
   …
}

A chamada a MyIteratorMethod não executa o corpo do método. Em vez disso, a chamada retorna IEnumerable<string> na variável elements.

Em uma iteração do loop foreach, o método MoveNext é chamado para elements. Essa chamada executará o corpo de MyIteratorMethod até que a próxima instrução yield return seja atingida. A expressão retornada pela instrução yield return determina não apenas o valor da variável element para consumo pelo corpo do loop, mas também a propriedade Current dos elementos que é IEnumerable<string>.

Em cada iteração subsequente do loop foreach, a execução do corpo do iterador continuará de onde parou, parando novamente quando atingir uma instrução yield return. O loop foreach é concluído quando o fim do método iterador ou uma instrução yield break é atingida.

Exemplo

O exemplo a seguir contém uma instrução yield return dentro de um loop for. Cada iteração do corpo da instrução foreach em Process cria uma chamada à função iteradora Power. Cada chamada à função iteradora prossegue para a próxima execução da instrução yield return que ocorre durante a próxima iteração do loop for.

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.

public class PowersOf2
{
    static void Main()
    {
        // Display powers of 2 up to the exponent of 8: 
        foreach (int i in Power(2, 8))
        {
            Console.Write("{0} ", i);
        }
    }

    public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent)
    {
        int result = 1;

        for (int i = 0; i < exponent; i++)
        {
            result = result * number;
            yield return result;
        }
    }

    // Output: 2 4 8 16 32 64 128 256
}

O exemplo a seguir demonstra um acessador get que é um iterador. No exemplo, cada instrução yield return retorna uma instância de uma classe definida pelo usuário.

public static class GalaxyClass
{
    public static void ShowGalaxies()
    {
        var theGalaxies = new Galaxies();
        foreach (Galaxy theGalaxy in theGalaxies.NextGalaxy)
        {
            Debug.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears.ToString());
        }
    }

    public class Galaxies
    {

        public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy
        {
            get
            {
                yield return new Galaxy { Name = "Tadpole", MegaLightYears = 400 };
                yield return new Galaxy { Name = "Pinwheel", MegaLightYears = 25 };
                yield return new Galaxy { Name = "Milky Way", MegaLightYears = 0 };
                yield return new Galaxy { Name = "Andromeda", MegaLightYears = 3 };
            }
        }

    }

    public class Galaxy
    {
        public String Name { get; set; }
        public int MegaLightYears { get; set; }
    }
}

Especificação da Linguagem C#

Para obter mais informações, consulte a Especificação da linguagem C#. A especificação da linguagem é a fonte definitiva para a sintaxe e o uso de C#.

Consulte também

Referência

foreach, in (Referência de C#)

Conceitos

Guia de Programação em C#

Outros recursos

Referência de C#

Iteradores (C# e Visual Basic)