0

Enumerableに関して「yield」キーワードがどのように機能するか説明していただけますか?例:以下のコードで、プログラムがIEnumerableタイプのオブジェクトを返す方法を理解できません。

class Program
    {
        static IEnumerable<T> Merge<T>(IEnumerable<T> left, IEnumerable<T> right)
            where T: IComparable<T>
        {
            IEnumerator<T> l = left.GetEnumerator();
            IEnumerator<T> r = right.GetEnumerator();

            bool l_has_data = l.MoveNext();
            bool r_has_data = r.MoveNext();

            while (l_has_data || r_has_data)
            {
                if (!l_has_data && r_has_data)
                {
                    yield return r.Current;
                    r_has_data = r.MoveNext();
                    continue;
                }
                if (!r_has_data && l_has_data)
                {
                    yield return l.Current;
                    l_has_data = l.MoveNext();
                    continue;
                }

                int comp = l.Current.CompareTo(r.Current);
                if (comp < 0)
                {
                    yield return l.Current;
                    l_has_data = l.MoveNext();
                }
                else if (comp > 0)
                {
                    yield return r.Current;
                    r_has_data = r.MoveNext();
                }
                else
                {
                    yield return l.Current;
                    yield return r.Current;
                    l_has_data = l.MoveNext();
                    r_has_data = r.MoveNext();
                }
            }
        }

'.Current'にカーソルを合わせると、'列挙子の現在の位置にある要素を取得する'と表示されます。

4

2 に答える 2

3

MSDNの日数:

yieldキーワードは、それが表示されるメソッドがイテレーターブロックであることをコンパイラーに通知します。コンパイラーは、イテレーター・ブロックで表現される動作を実装するためのクラスを生成します。iteratorブロックでは、yieldキーワードをreturnキーワードと一緒に使用して、列挙子オブジェクトに値を提供します。これは、たとえば、foreachステートメントの各ループで返される値です。


簡単に言えば:

yield returnを返すCollection of Object代わりにを返すsingle object

    static void Main(string[] args)
    {

        int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        // supposed u need to find all the numbers which are greater then 5
        // in general it could have been done like

        foreach (int number in numbers)
        {
            if (number > 5)
            {
                Console.WriteLine(number);
            }

        }

        // what if u needed the numbers that are greater then 5 multiple times, each time you would have to start a loop
        // yield return helps to return a collection of int
        var needed_numbers = NeededNumbers(numbers);

        foreach (int neededNumber in needed_numbers)
        {
            Console.WriteLine(neededNumber);
        }
    }

    private static IEnumerable<int> NeededNumbers(int[] nums)
    {
        foreach (int number in nums)
        {
            if (number > 5)
            {
                yield return number;
            }

        }
    }

DotNetPerlsからの引用

意味的には、yield returnステートメントはreturnステートメント(制御フローを呼び出し元のメソッドに渡す)と同等であり、その後にforeachループの次の反復でyieldステートメントへの「goto」が続きます。

于 2013-02-16T05:43:32.727 に答える
1

MS Docsから:

ステートメントでyieldcontextualキーワードを使用する場合、それが表示されるメソッド、演算子、またはgetアクセサーがイテレーターであることを示します。イールドを使用してイテレータを定義すると、カスタムコレクションタイプのIEnumerableおよびIEnumeratorパターンを実装するときに、明示的な追加クラス(列挙の状態を保持するクラス。例についてはIEnumeratorを参照)が不要になります。

于 2019-01-02T14:39:12.840 に答える