请参阅下面的编辑以重现我在此问题中描述的行为。
下面的程序永远不会结束,因为yield return
在 C# 中构造调用 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
loop 的行为就像一个无限循环。下面的程序确实结束了,异常显示在控制台上。
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 Update 2 中,无论我是在 Debug 还是 Release 中编译,上面的行为都是我所看到的。随着try
... catch
,程序以异常结束,如果没有异常,Visual Studio 永远不会关闭程序。
编辑 #3:固定 对我来说,@MartinBrown 的回答解决了这个问题。当我在“调试”>“选项”>“调试”>“常规”>“Unwind the call stack on unhandled exceptions”下取消选中 Visual Studio 的选项时,这个问题就消失了。当我再次选中该框时,问题又来了。
最佳答案
这里看到的行为不是代码中的错误;相反,它是 Visual Studio 调试器的副作用。这可以通过在 Visual Studio 中关闭堆栈展开来解决。尝试进入 Visual Studio 选项 Debugging/General 并取消选中“Unwind the call stack on unhandled exceptions”。然后再次运行代码。
发生的情况是,当您的代码遇到完全未处理的异常时,Visual Studio 会将调用堆栈展开到代码中导致异常的行之前。它这样做是为了让您可以编辑代码并继续执行编辑后的代码。
这里看到的问题看起来像一个无限循环,因为当您在调试器中重新开始执行时,要运行的下一行是刚刚导致异常的那一行。在调试器之外,调用堆栈将在未处理的异常上完全展开,因此不会导致您在调试器中遇到的相同循环。
此堆栈展开功能可以在设置中关闭,默认情况下处于启用状态。但是,将其关闭将使您无法编辑代码并继续操作,而无需先自行展开堆栈。然而,这很容易通过调用堆栈窗口或从异常助手中选择“启用编辑”来实现。
关于c# - 如何在 C# 中的 yield return 方法中正确抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38249895/