web-dev-qa-db-ja.com

「歩留まりの低下」とは何ですか。 C#で行うのですか?

私はMSDNでこの構文を見ました: yield break 、しかしそれが何をするのかわかりません。誰か知っている?

448
skb

反復子が終了したことを示します。 yield breakは、値を返さないreturnステートメントと考えることができます。

たとえば、関数をイテレータとして定義した場合、関数の本体は次のようになります。

for (int i = 0; i < 5; i++)
{
    yield return i;
}

Console.Out.WriteLine("You will see me");

ループがすべてのサイクルを完了した後、最後の行が実行され、コンソールアプリケーションにメッセージが表示されます。

あるいはyield breakでこんな感じです:

int i = 0;
while (true)
{
    if (i < 5)
    {
        yield return i;
    }
    else
    {
        // note that i++ will not be executed after this
        yield break;
    }
    i++;
}

Console.Out.WriteLine("Won't see me");

この場合、関数を早く残したので、最後のステートメントは実行されません。

487
Damir Zekić

イテレータブロックを終了します(例えば、IEnumerableにそれ以上要素がないと言います)。

51
Brian

最後に到達したことをイテレータに伝えます。

例として:

public interface INode
{
    IEnumerable<Node> GetChildren();
}

public class NodeWithTenChildren : INode
{
    private Node[] m_children = new Node[10];

    public IEnumerable<Node> GetChildren()
    {
        for( int n = 0; n < 10; ++n )
        {
            yield return m_children[ n ];
        }
    }
}

public class NodeWithNoChildren : INode
{
    public IEnumerable<Node> GetChildren()
    {
        yield break;
    }
}
29
Trap

yieldは基本的にIEnumerable<T>メソッドを(プリエンプティブではなく)協調的にスケジュールされたスレッドと同じように動作させます。

yield returnは、CPUの制御を放棄するために「schedule」または「sleep」関数を呼び出すスレッドのようなものです。スレッドのように、IEnumerable<T>メソッドはその直後の時点でコントロールを取り戻します。すべてのローカル変数はコントロールが放棄される前と同じ値を持ちます。

yield breakは、その機能の終わりに達して終了するスレッドのようなものです。

人々は「ステートマシン」について話しますが、ステートマシンはすべて「スレッド」です。スレッドは何らかの状態(すなわちローカル変数の値)を持ち、それがスケジュールされるたびに新しい状態に達するために何らかのアクションをとる。 yieldに関する重要な点は、これまで使用してきたオペレーティングシステムのスレッドとは異なり、それを使用するコードは、反復が手動で進められるか終了するまで時間内に凍結されることです。

19
Matthew

イテレーター・ブロックの全主題は、Jon Skeetの本の 無料サンプルの章C#in Depth で詳しく説明されています。

10
Marc Gravell

ここで http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/ はとても良い例です。

 public static IEnumerable <int>範囲(int min、int max)
 {
 while(true)
 {
 if(min> = max)
 {
イールドブレイク; 
} 
イールドリターンmin ++; 
} 
} 

yield breakステートメントがメソッド内でヒットした場合、そのメソッドの実行はリターンせずに停止します。あなたが何も結果を与えたくないとき、あなたは歩留まり休憩を使うことができるとき、いくつかの時間状況があります。

7
Yuriy Zaletskyy

yield breakステートメントは列挙を停止させます。実際には、yield breakは追加項目を返さずに列挙を完了します。

反復子メソッドが反復を停止できる方法は、実際には2つあると考えてください。ある場合には、メソッドのロジックはすべての項目を返した後にメソッドを自然に終了することができます。これが一例です。

IEnumerable<uint> FindPrimes(uint startAt, uint maxCount)
{
    for (var i = 0UL; i < maxCount; i++)
    {
        startAt = NextPrime(startAt);
        yield return startAt;
    }

    Debug.WriteLine("All the primes were found.");
}

上記の例では、maxCountの素数が見つかると、イテレータメソッドは当然実行を停止します。

yield breakステートメントは、イテレータが列挙を中止するもう1つの方法です。それは列挙から早く抜け出すための方法です。これは上記と同じ方法です。今回は、メソッドが実行できる時間に制限があります。

IEnumerable<uint> FindPrimes(uint startAt, uint maxCount, int maxMinutes)
{
    var sw = System.Diagnostics.Stopwatch.StartNew();
    for (var i = 0UL; i < maxCount; i++)
    {
        startAt = NextPrime(startAt);
        yield return startAt;

        if (sw.Elapsed.TotalMinutes > maxMinutes)
            yield break;
    }

    Debug.WriteLine("All the primes were found.");
}

yield breakへの呼び出しに注目してください。実際には、それは早く列挙を終了しています。

yield breakは単なる普通のbreakとは動作が異なることにも注意してください。上記の例では、yield breakは、Debug.WriteLine(..)を呼び出さずにメソッドを終了します。

6
Wallace Kelly

あなたが「イールドブレイクは本当に何をするのか」によって意味するものであれば、「それはどのように機能するのですか」 - 詳細についてはRaymond Chenのブログを参照してください http://blogs.msdn.com/oldnewthing/archive/2008/08/ 12/8849519.aspx

C#イテレータは、非常に複雑なコードをいくつか生成します。

4
Tony Lee

イールドブレイクは、前回のリターンを表すための単なる方法であり、値を返さないことです。

例えば

// returns 1,2,3,4,5
IEnumerable<int> CountToFive()
{
    yield return 1;
    yield return 2;
    yield return 3;
    yield return 4;
    yield return 5;
    yield break;
    yield return 6;
    yield return 7;
    yield return 8;
    yield return 9;
 }
3
John ClearZ