yield (Referencia de C#)yield (C# Reference)

Cuando se usa la palabra clave yield en una instrucción, se indica que el método, el operador o el descriptor de acceso get en el que aparece es un iterador.When you use the yield keyword in a statement, you indicate that the method, operator, or get accessor in which it appears is an iterator. Al usar yield para definir un iterador ya no es necesaria una clase adicional explícita (la clase que retiene el estado para una enumeración, consulte IEnumerator<T> para ver un ejemplo) al implementar los patrones IEnumerable y IEnumerator para un tipo de colección personalizado.Using yield to define an iterator removes the need for an explicit extra class (the class that holds the state for an enumeration, see IEnumerator<T> for an example) when you implement the IEnumerable and IEnumerator pattern for a custom collection type.

En el ejemplo siguiente se muestran las dos formas de la instrucción yield.The following example shows the two forms of the yield statement.

yield return <expression>;  
yield break;  

ComentariosRemarks

Utilice una instrucción yield return para devolver cada elemento de uno en uno.You use a yield return statement to return each element one at a time.

Para consumir un método iterador, use una instrucción foreach o una consulta LINQ.You consume an iterator method by using a foreach statement or LINQ query. Cada iteración del bucle foreach llama al método iterador.Each iteration of the foreach loop calls the iterator method. Cuando se alcanza una instrucción yield return en el método iterador, se devuelve expression y se conserva la ubicación actual en el código.When a yield return statement is reached in the iterator method, expression is returned, and the current location in code is retained. La ejecución se reinicia desde esa ubicación la próxima vez que se llama a la función del iterador.Execution is restarted from that location the next time that the iterator function is called.

Puede usar una instrucción yield break para finalizar la iteración.You can use a yield break statement to end the iteration.

Para obtener más información sobre los iteradores, vea Iteradores.For more information about iterators, see Iterators.

Métodos de iterador y descriptores de acceso getIterator Methods and get Accessors

La declaración de un iterador debe cumplir los requisitos siguientes:The declaration of an iterator must meet the following requirements:

El tipo yield de un iterador que devuelve IEnumerable o IEnumerator es object.The yield type of an iterator that returns IEnumerable or IEnumerator is object. Si el iterador devuelve IEnumerable<T> o IEnumerator<T>, debe haber una conversión implícita del tipo de la expresión en la instrucción yield return al parámetro de tipo genérico.If the iterator returns IEnumerable<T> or IEnumerator<T>, there must be an implicit conversion from the type of the expression in the yield return statement to the generic type parameter .

No se puede incluir una instrucción yield return ni yield break en los métodos que tengan las siguientes características:You can't include a yield return or yield break statement in methods that have the following characteristics:

  • Métodos anónimos.Anonymous methods. Para obtener más información, vea Métodos anónimos.For more information, see Anonymous Methods.

  • Métodos que contienen bloques inseguros.Methods that contain unsafe blocks. Para obtener más información, vea unsafe.For more information, see unsafe.

Control de excepcionesException Handling

Una instrucción yield return no puede encontrarse en un bloque try-catch.A yield return statement can't be located in a try-catch block. Una instrucción yield return puede encontrarse en el bloque try de una instrucción try-finally.A yield return statement can be located in the try block of a try-finally statement.

Una instrucción yield break puede encontrarse en un bloque try o un bloque catch, pero no en un bloque finally.A yield break statement can be located in a try block or a catch block but not a finally block.

Si el cuerpo foreach (fuera del método iterador) produce una excepción, se ejecuta un bloque finally en el método iterador.If the foreach body (outside of the iterator method) throws an exception, a finally block in the iterator method is executed.

Implementación técnicaTechnical Implementation

El código siguiente devuelve un valor IEnumerable<string> desde un método iterador y, a continuación, recorre sus elementos en iteración.The following code returns an IEnumerable<string> from an iterator method and then iterates through its elements.

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

La llamada a MyIteratorMethod no ejecuta el cuerpo del método.The call to MyIteratorMethod doesn't execute the body of the method. En su lugar, la llamada devuelve un valor IEnumerable<string> en la variable elements.Instead the call returns an IEnumerable<string> into the elements variable.

En una iteración del bucle foreach, se llama al método MoveNext para elements.On an iteration of the foreach loop, the MoveNext method is called for elements. Esta llamada ejecuta el cuerpo de MyIteratorMethod hasta que se alcanza la siguiente instrucción yield return.This call executes the body of MyIteratorMethod until the next yield return statement is reached. La expresión devuelta por la instrucción yield return determina no solo el valor de la variable element para que la utilice el cuerpo del bucle, sino también la propiedad Current de elements, que es un valor IEnumerable<string>.The expression returned by the yield return statement determines not only the value of the element variable for consumption by the loop body but also the Current property of elements, which is an IEnumerable<string>.

En cada iteración subsiguiente del bucle foreach, la ejecución del cuerpo del iterador continúa desde donde se dejó, deteniéndose de nuevo al alcanzar una instrucción yield return.On each subsequent iteration of the foreach loop, the execution of the iterator body continues from where it left off, again stopping when it reaches a yield return statement. El bucle foreach se completa al alcanzar el fin del método iterador o una instrucción yield break.The foreach loop completes when the end of the iterator method or a yield break statement is reached.

EjemploExample

El ejemplo siguiente tiene una instrucción yield return que está dentro de un bucle for.The following example has a yield return statement that's inside a for loop. Cada iteración del cuerpo de instrucción foreach en el método Main crea una llamada a la función de iterador Power.Each iteration of the foreach statement body in the Main method creates a call to the Power iterator function. Cada llamada a la función de iterador prosigue con la siguiente ejecución de la instrucción yield return, que se produce durante la siguiente iteración del bucle for.Each call to the iterator function proceeds to the next execution of the yield return statement, which occurs during the next iteration of the for loop.

El tipo de valor devuelto del método iterador es IEnumerable, que es un tipo de interfaz de iteradores.The return type of the iterator method is IEnumerable, which is an iterator interface type. Cuando se llama al método iterador, este devuelve un objeto enumerable que contiene las potencias de un número.When the iterator method is called, it returns an enumerable object that contains the powers of a number.

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
}

EjemploExample

En el ejemplo siguiente se muestra un descriptor de acceso get que es un iterador.The following example demonstrates a get accessor that is an iterator. En el ejemplo, cada una de las instrucciones yield return devuelve una instancia de una clase definida por el usuario.In the example, each yield return statement returns an instance of a user-defined class.

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; }
    }
}

Especificación del lenguaje C#C# Language Specification

Para obtener más información, consulte la Especificación del lenguaje C#.For more information, see the C# Language Specification. La especificación del lenguaje es la fuente definitiva de la sintaxis y el uso de C#.The language specification is the definitive source for C# syntax and usage.

Vea tambiénSee Also

Referencia de C#C# Reference
Guía de programación de C#C# Programming Guide
foreach, inforeach, in
IteradoresIterators