この問題で説明する動作を再現するために、以下の編集を参照してください。Cで例外を正しくスローする方法#
例外がスローされたときにC#のyield return
コンストラクトがGetStrings()
メソッドを無期限に呼び出すため、次のプログラムは終了しません。
class Program
{
static void Main(string[] args)
{
// I expect the Exception to be thrown here, but it's not
foreach (var str in GetStrings())
{
Console.WriteLine(str);
}
}
private static IEnumerable<string> GetStrings()
{
// REPEATEDLY throws this exception
throw new Exception();
yield break;
}
}
この簡単な例では、私は明らかに代わりreturn Enumerable.Empty<string>();
を使用することができ、そして問題が消えます。しかし、もっと興味深い例では、私は例外が一度スローされると期待して、メソッドが呼び出されなくなり、IEnumerable
を「消費する」メソッドに例外をスローします。
この現象は発生する可能性がありますか?
EDIT:問題は私が最初に考えたものとは異なります。上のプログラムは終了せず、foreach
ループは無限ループのように動作します。以下のプログラムは終了し、例外がコンソールに表示されます。
class Program
{
static void Main(string[] args)
{
try
{
foreach (var str in GetStrings())
{
Console.WriteLine(str);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static IEnumerable<string> GetStrings()
{
throw new Exception();
yield break;
}
}
はなぜtry
... catch
ブロックは、この場合の違いを作るのですか?これは私にとって非常に奇妙なようです。 @AndrewKilburnに感謝してくれてありがとうございました。
EDIT#2: コマンドプロンプトから、プログラムはどちらの場合も同じことを実行します。 Visual Studio Enterprise 2015 Update 2では、DebugまたはReleaseでコンパイルしても、上記の動作が表示されます。 try
... catch
では、プログラムは例外で終了し、Visual Studioがプログラムを終了することはありません。
EDIT#3:修正済み 私の場合、問題は@MartinBrownの回答によって解決されました。 [デバッグ]> [オプション]> [デバッグ]> [一般]> [未処理の例外でコールスタックをアンワインド]のVisual Studioのオプションをオフにすると、この問題は解決しません。ボックスにもう一度チェックを入れると、問題が戻ってきます。トライキャッチでそれを置く
は
私はそれを試してみると、一度だけスローします。 'foreach'を' try catch'でラップする場合、例外は一度だけキャッチされ、プログラムは終了します。私はそれを正しく理解しましたか? – Szer
うーん、私はその行動を見ていないよ。私はもう一度確認してみましょう。私が見ている動作は例外がスローされ、何とかシーンの後ろで捕まえられ、 'foreach'ループが無限ループのように振る舞います。 –
@Szer私の編集を参照してください、 'try' ...' catch'ブロックは、foreachループが無限ループとして機能するかどうかを変えるようです。あなたには意味がありますか? –