私はこの構文をMSDNで見ました:がyield break
、それが何をするのかわかりません。誰か知っていますか?
MyList.Add(...)
単に行うようにコーディングする必要はありませんyield return ...
。ループから途中で抜け出し、使用する仮想バッキングリストを返す必要がある場合yield break;
私はこの構文をMSDNで見ました:がyield break
、それが何をするのかわかりません。誰か知っていますか?
MyList.Add(...)
単に行うようにコーディングする必要はありませんyield return ...
。ループから途中で抜け出し、使用する仮想バッキングリストを返す必要がある場合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");
この場合、関数を早く終了したため、最後のステートメントは実行されません。
break
代わりになるだけyield break
ですか?コンパイラはそれについて文句を言いません。
break
この場合、@ orad simple はループを停止しますが、メソッドの実行を中止しないため、最後の行が実行され、「Wo n't see me text」が実際に表示されます。
NullReferenceException
は、IEnumerableの列挙子を取得できますが、yieldブレークでは取得できません(要素のないインスタンスがあります)。
yield return x
アラートを使用して、このメソッドにEnumerator
オブジェクトを作成するための構文糖にしたいコンパイラー。この列挙子には、メソッドMoveNext()
とプロパティがありますCurrent
。MoveNext()はyield return
ステートメントまでメソッドを実行し、その値をに変換しCurrent
ます。次回MoveNextが呼び出されると、そこから実行が続行されます。yield break
Currentをnullに設定し、この列挙子の終了を通知して、a foreach (var x in myEnum())
が終了するようにします。
イテレータブロックを終了します(たとえば、IEnumerableに要素がなくなると言います)。
yield
キーワードを使用すると、コレクションを双方向に反復できます。さらに、コレクションの次の要素すべてを一列に
yield
。私はあなたが間違っていると言っているのではなく、あなたが示唆していることがわかります。ただし、学術的には.NETにはイテレータはなく、列挙子(一方向、前方)のみです。stdc++とは異なり、CTS / CLRで定義された「汎用イテレータフレームワーク」はありません。LINQは、yield return
コールバックメソッドを利用する拡張メソッドとのギャップを埋めるのに役立ちますが、これらはファーストクラスの拡張メソッドであり、ファーストクラスのイテレーターではありません。結果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の制御を放棄するために「スケジュール」または「スリープ」関数を呼び出すスレッドのようなものです。スレッドのように、このIEnumerable<T>
メソッドは直後の時点でコントロールを取り戻します。すべてのローカル変数は、コントロールが放棄される前と同じ値を持っています。
yield break
スレッドがその機能の最後に到達して終了するようなものです。
人々は「ステートマシン」について話しますが、ステートマシンはすべてすべて「スレッド」です。スレッドにはいくつかの状態(つまり、ローカル変数の値)があり、スケジュールされるたびに、新しい状態に到達するためにいくつかのアクションを実行します。重要な点yield
は、これまで使用していたオペレーティングシステムのスレッドとは異なり、それを使用するコードは、反復が手動で進められるか終了されるまで時間内に凍結されるということです。
イテレータブロックの全トピックについては、Jon Skeetの書籍「C#in Depth」のこの無料サンプルの章で十分に説明されています。
この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
文はイテレータが列挙中止するための別の方法です。これは、列挙を早く抜け出す方法です。上記と同じ方法です。今回は、メソッドが実行できる時間に制限があります。
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(..)
。
ここでhttp://www.alteridem.net/2007/08/22/the-yield-statement-in-c/は非常に良い例です:
public static IEnumerable <int> Range(int min、int max) { ながら(true) { if(min> = max) { 歩留まり; } イールドリターンmin ++; } }
そして説明は、yield break
ステートメントがメソッド内でヒットした場合、そのメソッドの実行はリターンなしで停止するということです。結果を出したくない場合は、いくつかの時間的な状況があり、降伏ブレークを使用できます。
「イールドブレークが実際に何をするのか」とは、「どのように機能するのか」です。詳細については、レイモンドチェンのブログを参照してください。https://devblogs.microsoft.com/oldnewthing/20080812-00/?p = 21273
C#イテレータは非常に複雑なコードを生成します。
yieldキーワードは、returnキーワードと一緒に使用され、列挙子オブジェクトに値を提供します。yield returnは、返される値を指定します。yield returnステートメントに到達すると、現在の場所が保存されます。反復子が次に呼び出されたときに、この場所から実行が再開されます。
例を使用して意味を説明するには:
public IEnumerable<int> SampleNumbers() { int counter = 0; yield return counter; counter = counter + 2; yield return counter; counter = counter + 3; yield return counter ; }
これが繰り返されるときに返される値は、0、2、5です。
この例のカウンター変数はローカル変数であることに注意することが重要です。2の値を返す2回目の反復の後、counterという名前のローカル変数の以前の値である2 を維持しながら、3回目の反復は以前の場所から開始します。
yield break
しているのか説明しませんでした
yield return
実際には複数の値を返すことをサポートしていないと思います。多分それはあなたが実際に意味したものではないかもしれませんが、それは私がそれを読む方法です。
yield break
などの言語レベルの列挙子が含まれていないためです。foreach
列挙子を使用すると、yield break
実際の値が提供されます。この例は、展開されたループのように見えます。現実の世界ではこのコードを見ることはほとんどありません(確かにいくつかのエッジケースを考えることができます)。また、ここには "反復子"はありません。「イテレータブロック」は、言語仕様の問題として、メソッドを超えて拡張することはできません。どのような実際に戻されていることは「可算」で、以下を参照してください。stackoverflow.com/questions/742497/...