c# - 如何在 C# 中的 yield return 方法中正确抛出异常

标签 c# exception yield-return

请参阅下面的编辑以重现我在此问题中描述的行为。

下面的程序永远不会结束,因为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/

相关文章:

c# - 捕获失败的授权策略

c# - 如何在Mac的Visual Studio中清除macOS终端板?

java - eclipse 强制异常功能

java - 如何抛出不会终止我的程序的 IllegalArgumentException?

c# - 为什么在 switch 语句中 yield return 之后需要 break?

c# - 复制 IEnumerable,替换一个项目

c# - 局部变量可以命名为 yield

c# - 曼哈顿旅游问题的对角线计算

c# - 以编程方式解除事件处理程序的 Hook

c++ - 读取格式不正确的文件时应该抛出什么类型的 std::exception?