yield (справочник по C#)yield (C# Reference)

Использование в операторе контекстного ключевого слова yield означает, что метод, оператор или метод доступа get, в котором присутствует это ключевое слово, является итератором.When you use the yield contextual keyword in a statement, you indicate that the method, operator, or get accessor in which it appears is an iterator. Использование yield для определения итератора исключает необходимость применения явного дополнительного класса (в котором содержится состояние перечисления; в качестве примера см. IEnumerator<T>) при реализации шаблонов IEnumerable и IEnumerator для пользовательского типа коллекции.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.

В следующем примере показаны две формы оператора yield.The following example shows the two forms of the yield statement.

yield return <expression>;
yield break;

ПримечанияRemarks

Оператор yield return используется для возврата каждого элемента по одному.You use a yield return statement to return each element one at a time.

Последовательность, которая возвращается после выполнения метода итератора, можно использовать с помощью оператора foreach или запроса LINQ.The sequence returned from an iterator method can be consumed by using a foreach statement or LINQ query. Каждая итерация цикла foreach вызывает метод итератора.Each iteration of the foreach loop calls the iterator method. При достижении в методе итератора оператора yield return возвращается expression и сохраняется текущее расположение в коде.When a yield return statement is reached in the iterator method, expression is returned, and the current location in code is retained. При следующем вызове функции итератора выполнение возобновляется с этого места.Execution is restarted from that location the next time that the iterator function is called.

Для завершения итерации можно использовать оператор yield break.You can use a yield break statement to end the iteration.

Дополнительные сведения об итераторах см. в разделе Итераторы.For more information about iterators, see Iterators.

Методы итератора и методы доступа getIterator methods and get accessors

Объявление итератора должно соответствовать следующим требованиям.The declaration of an iterator must meet the following requirements:

Тип yield итератора, который возвращает IEnumerable или IEnumerator, — object.The yield type of an iterator that returns IEnumerable or IEnumerator is object. Если итератор возвращает IEnumerable<T> или IEnumerator<T>, необходимо выполнить неявное преобразование из типа выражения в операторе yield return в параметр универсального типа.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 .

Нельзя включать инструкцию yield return или yield break:You can't include a yield return or yield break statement in:

Обработка исключенийException handling

Оператор yield return нельзя размещать в блоке try-catch.A yield return statement can't be located in a try-catch block. Оператор yield return можно размещать в блоке try оператора try-finally.A yield return statement can be located in the try block of a try-finally statement.

Оператор yield break можно размещать в блоке try или catch, но не в блоке finally.A yield break statement can be located in a try block or a catch block but not a finally block.

Если тело оператора foreach (вне метода итератора) вызывает исключение, выполняется блок finally в методе итератора.If the foreach body (outside of the iterator method) throws an exception, a finally block in the iterator method is executed.

Техническая реализацияTechnical implementation

В следующем коде возвращается объект IEnumerable<string> из метода итератора и затем выполняется перебор его элементов.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)
{
   ...
}

При вызове MyIteratorMethod тело метода не выполняется.The call to MyIteratorMethod doesn't execute the body of the method. Вместо этого вызов возвращает IEnumerable<string> в переменную elements.Instead the call returns an IEnumerable<string> into the elements variable.

В итерации цикла foreach метод MoveNext вызывается для elements.On an iteration of the foreach loop, the MoveNext method is called for elements. Этот вызов выполняет тело MyIteratorMethod до достижения следующего оператора yield return.This call executes the body of MyIteratorMethod until the next yield return statement is reached. Выражение, возвращаемое оператором yield return, определяет не только значение переменной element для использования телом цикла, но и свойство Current объекта elements, представляющее собой 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>.

В каждой последующей итерации цикла foreach выполнение тела итератора продолжается с места остановки и при достижении оператора 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. Цикл foreach завершается при достижении конца метода итератора или оператора yield break.The foreach loop completes when the end of the iterator method or a yield break statement is reached.

ПримерExample

В следующем примере имеется оператор yield return, расположенный в цикле for.The following example has a yield return statement that's inside a for loop. Каждая итерация тела оператора foreach в методе Main создает вызов функции итератора Power.Each iteration of the foreach statement body in the Main method creates a call to the Power iterator function. При каждом вызове функции итератора происходит переход к следующему выполнению оператора yield return, которое осуществляется во время следующей итерации цикла 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.

Возвращаемый тип метода итератора — IEnumerable (тип интерфейса итератора).The return type of the iterator method is IEnumerable, which is an iterator interface type. При вызове метода итератора возвращается перечисляемый объект, содержащий степени числа.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
}

ПримерExample

В следующем примере демонстрируется метод доступа get, представляющий собой итератор.The following example demonstrates a get accessor that is an iterator. В этом примере каждый оператор yield return возвращает экземпляр пользовательского класса.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; }
    }
}

Спецификация языка C#C# language specification

Дополнительные сведения см. в спецификации языка C#.For more information, see the C# Language Specification. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.The language specification is the definitive source for C# syntax and usage.

См. такжеSee also