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 迴圈的每個反覆項目都會呼叫 Iterator 方法。Each iteration of the foreach loop calls the iterator method. 當 Iterator 方法中到達 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. 下一次呼叫 Iterator 函式時,便會從這個位置重新開始執行。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.

如需迭代器的詳細資訊,請參閱 Iterators (迭代器)。For more information about iterators, see Iterators.

Iterator 方法和 get 存取子Iterator methods and get accessors

迭代器的宣告必須符合下列需求:The declaration of an iterator must meet the following requirements:

傳回 yieldIEnumerableIEnumerator 類型迭代器為 objectThe 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 returnyield 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-finally 陳述式的 try 區塊內。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 主體 (在 Iterator 方法之外) 擲回例外狀況,則會執行 Iterator 方法中的 finally 區塊。If the foreach body (outside of the iterator method) throws an exception, a finally block in the iterator method is executed.

技術實作Technical implementation

下列程式碼會從 Iterator 方法傳回 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 變數的值,也會判斷 elementsCurrent 屬性,其為 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. 當 Iterator 方法結束或到達 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. Main 方法中 foreach 陳述式主體的每個反覆項目都會建立對 Power Iterator 函式的呼叫。Each iteration of the foreach statement body in the Main method creates a call to the Power iterator function. 每次呼叫 Iterator 函式都會執行下一個 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.

Iterator 方法的傳回類型是 IEnumerable,其為 Iterator 介面類型。The return type of the iterator method is IEnumerable, which is an iterator interface type. 呼叫 Iterator 方法時,它會傳回包含數字乘冪的可列舉物件。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