【发布时间】:2016-07-08 16:35:45
【问题描述】:
请参阅下面的编辑以重现我在此问题中描述的行为。
以下程序永远不会结束,因为 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 的方法中抛出异常。
有没有办法产生这种行为?
编辑:好的,问题与我最初想的不同。上面的程序没有结束,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 已经为我指出了这一点。
编辑#2:
在命令提示符下,程序在两种情况下都执行相同的操作。在 Visual Studio Enterprise 2015 更新 2 中,无论我在 Debug 还是 Release 中编译,上面的行为都是我所看到的。使用try ... catch,程序以异常结束,没有它,Visual Studio 永远不会关闭程序。
编辑 #3:已修复 对我来说,@MartinBrown 的回答解决了这个问题。当我在 Debug > Options > Debugging > General > “Unwind the call stack on unhandled exceptions”下取消选中 Visual Studio 的选项时,这个问题就消失了。当我再次选中该框时,问题又回来了。
【问题讨论】:
-
我试过了,它只抛出一次。在用
try catch包装foreach的情况下,异常也只被捕获一次并且程序退出。我理解正确吗? -
嗯,我没有看到这种行为。让我再次确认一下。我看到的行为是抛出异常,它在幕后以某种方式被捕获,
foreach循环的行为就像一个无限循环。 -
我的版本和你一模一样,操作系统也一模一样。在任何抖动和任何框架目标以及任何可用的调试引擎上都会像一吨砖一样崩溃。你需要修好你的机器。
-
根据您的最后一条评论,您看到的行为似乎是由 Visual Studio 的调试器引起的,该调试器吞下了未处理的异常(不带 try/catch 的版本)?我是否正确解释(编辑#2)?我什至不确定 VS 中是否有这样的设置可以做到这一点,但也许它会有助于发布你的 VS 调试设置的屏幕截图。
-
n/m,我看到你已经接受了我所想的答案。
标签: c# exception yield-return