24

次のコードのbreak後でコンパイラがそれが必要だと考える理由を誰か教えてもらえますか?yield return

foreach (DesignerNode node in nodeProvider.GetNodes(span, node => node.NodeType != NDjango.Interfaces.NodeType.ParsingContext))
{
    switch (node.ErrorMessage.Severity)
    {
        case -1:
        case 0:
            continue;
        case 1:
            yield return new TagSpan<ErrorTag>(node.SnapshotSpan, new ErrorTag(PredefinedErrorTypeNames.Warning));
            break;
        default:
            yield return new TagSpan<ErrorTag>(node.SnapshotSpan, new ErrorTag(PredefinedErrorTypeNames.SyntaxError));
            break;
    }
}
4

3 に答える 3

31

yield return はイテレータ ジェネレータの単なる構文糖衣であり、実際にはどのメソッドも終了していないためです。また、C# では、 switchステートメントでのフォールスルーが許可されていません (とにかく、ここでフォールスルーが必要なようには見えません)。

于 2010-03-01T19:50:01.870 に答える
17

switch ステートメントで return yield の後に break が必要なのはなぜですか?

質問は、間違った前提を前提としています。switch ステートメントの yield return の後にbreak ステートメントは必要ありません。例えば:

switch(x)
{
case 123:
    yield return 456;
    M();
    throw new Exception();
case 789: // and so on

ここでは、ブレークが続かない switch ステートメントに yield リターンがあります。この後に M() の呼び出しが続き、次に throw ステートメントが続きます。それは完全に合法です。

本当のルールは、スイッチ セクションの終点が到達可能であってはならないということです

break、continue、return、goto、return、および throw のエンド ポイントには到達できません。これらのステートメントはすべて別の場所に分岐して戻ってこないため、それらの直後のコード トークンに到達できないからです。これは、たとえば、別の場所に分岐してから戻ってくるメソッド呼び出しや、制御を呼び出し元に戻すyield returnとは対照的です。呼び出し元が制御を反復子ブロックに戻すと、yield リターンが中断されたところから制御が取得されるため、yield リターンの終点に到達できます。

このテーマに興味がある場合は、仕様のセクション 8.1 を読むことをお勧めします。

于 2010-03-01T23:27:03.967 に答える
2

「通常の」リターンには 2 つの機能があります。

  1. 関数の戻り値をマークします。
  2. 制御を呼び出し元に転送します。

ýfield return は戻り値のみをマークします。制御フローには影響しません。yield return ステートメントの後、プログラムの実行は、他の switch-case ステートメントと同様に、サンプル内でブレークが必要な次の行に続きます。

于 2010-03-01T19:52:46.763 に答える