2

コレクションを列挙するための Yield の使用を理解しようとしています。私はこの基本的なコードを書きました:

static void Main(string[] args)
{
    Iterate iterate = new Iterate();
    foreach (int i in iterate.EnumerateList())
    {
        Console.Write("{0}", i);
    }
    Console.ReadLine();
}

class Iterate
{
    public IEnumerable<int> EnumerateList()
    {
        List<int> lstNumbers = new List<int>();

        lstNumbers.Add(1);
        lstNumbers.Add(2);
        lstNumbers.Add(3);
        lstNumbers.Add(4);
        lstNumbers.Add(5);

        foreach (int i in lstNumbers)
        {
            yield return i;
        }
    }
}

return i(1)の代わりに単純に使用するとどうなりyield return iますか?

(2) Yield を使用する利点は何ですか?

編集**

foreach上記のコードでは、 2回使用するのはオーバーヘッドだと思います。メソッドの1main function番目と 2 番目EnumerateListです。

4

4 に答える 4

8

を使用yield return iすると、このメソッドはiteratorになります。IEnumerable<int>ループ全体から一連の値を作成します。

を使用return iすると、単一のint値が返されます。あなたの場合、メソッドの戻り値の型がIEnumerable<int>、notであるため、これによりコンパイラエラーが発生しますint

この特定の例ではlstNumbers、イテレータを使用する代わりに、個人的には戻ります。ただし、リストなしでこれを次のように書き換えることができます。

public IEnumerable<int> EnumerateList()
{
    yield return 1;
    yield return 2;
    yield return 3;
    yield return 4;
    yield return 5;
}

あるいは:

public IEnumerable<int> EnumerateList()
{
    for (int i=1;i<=5;++i)
        yield return i;
}

これは、コレクションのように振る舞いたいクラスを作成する場合に非常に便利です。カスタム型を手動で実装するには、多くの場合、カスタム クラスなどを作成する必要があります。イテレータが登場する前は、C# でカスタム コレクションを実装するためのIEnumerable<T>この古いサンプルに示されているように、大量のコードが必要でした。

于 2013-02-15T17:54:54.020 に答える
2

Reedが言うように、を使用yieldするとイテレータを実装できます。イテレータの主な利点は、遅延評価が可能になることです。つまり、必要な場合を除いて、結果全体を具体化する必要はありません。

Directory.GetFilesBCLから検討してください。を返しますstring[]。つまり、すべてのファイルを取得し、名前を配列に入れてから返す必要があります。対照的に、をDirectory.EnumerateFiles返しますIEnumerable<string>。つまり、呼び出し元は結果セットを処理する責任があります。つまり、呼び出し元はいつでもコレクションの列挙をオプトアウトできます。

于 2013-02-15T18:00:50.633 に答える
1

このyieldキーワードにより、コンパイラは関数を列挙子オブジェクトに変換します。

yield returnステートメントは単に関数を終了して 1 つの値を返すのではなく、次の値が列挙子から要求されたときにその時点で再開できるように、コードを状態のままにします。

于 2013-02-15T17:59:00.323 に答える
1

i は int であり IEnumerable ではないため、 i だけを返すことはできません。コンパイルさえしません。IEnumerable のインターフェイスを実装しているため、lstNumbers を返すこともできました。

コンパイラが列挙可能なものの構築を処理し、最初にリストを構築する必要がないため、私はyield returnを好みます。したがって、私にとっては、すでにインターフェイスを実装しているものがあれば、それを構築する必要があり、他の場所では使用しない場合はそれを返します。

于 2013-02-15T17:59:08.837 に答える