私はMSDNでこの構文を見ました: yield break
、しかしそれが何をするのかわかりません。誰か知っている?
反復子が終了したことを示します。 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");
この場合、関数を早く残したので、最後のステートメントは実行されません。
イテレータブロックを終了します(例えば、IEnumerableにそれ以上要素がないと言います)。
最後に到達したことをイテレータに伝えます。
例として:
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;
}
}
yield
は基本的にIEnumerable<T>
メソッドを(プリエンプティブではなく)協調的にスケジュールされたスレッドと同じように動作させます。
yield return
は、CPUの制御を放棄するために「schedule」または「sleep」関数を呼び出すスレッドのようなものです。スレッドのように、IEnumerable<T>
メソッドはその直後の時点でコントロールを取り戻します。すべてのローカル変数はコントロールが放棄される前と同じ値を持ちます。
yield break
は、その機能の終わりに達して終了するスレッドのようなものです。
人々は「ステートマシン」について話しますが、ステートマシンはすべて「スレッド」です。スレッドは何らかの状態(すなわちローカル変数の値)を持ち、それがスケジュールされるたびに新しい状態に達するために何らかのアクションをとる。 yield
に関する重要な点は、これまで使用してきたオペレーティングシステムのスレッドとは異なり、それを使用するコードは、反復が手動で進められるか終了するまで時間内に凍結されることです。
イテレーター・ブロックの全主題は、Jon Skeetの本の 無料サンプルの章C#in Depth で詳しく説明されています。
ここで 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
ステートメントがメソッド内でヒットした場合、そのメソッドの実行はリターンせずに停止します。あなたが何も結果を与えたくないとき、あなたは歩留まり休憩を使うことができるとき、いくつかの時間状況があります。
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(..)
を呼び出さずにメソッドを終了します。
あなたが「イールドブレイクは本当に何をするのか」によって意味するものであれば、「それはどのように機能するのですか」 - 詳細についてはRaymond Chenのブログを参照してください http://blogs.msdn.com/oldnewthing/archive/2008/08/ 12/8849519.aspx
C#イテレータは、非常に複雑なコードをいくつか生成します。
イールドブレイクは、前回のリターンを表すための単なる方法であり、値を返さないことです。
例えば
// 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;
}