【问题标题】:C# - How to create a non-detectable infinite loop?C# - 如何创建不可检测的无限循环?
【发布时间】:2011-01-19 18:24:33
【问题描述】:

这只是一个“我很好奇”的问题。

在深入的 C# 中,Jon Skeet 谈到了 lambda 表达式:
“如果存在非 void 返回类型,则每个代码路径都必须返回兼容的值。”(第 233 页)

脚注接着说:
“当然,抛出异常的代码路径不需要返回值,可检测的无限循环也不需要。”(第 233 页)

我想知道什么是不可检测的无限循环?

这只能通过逻辑来完成吗?还是通过使用数据库或文件系统等外部因素来完成?

【问题讨论】:

  • @JonSkeet 也许他可以澄清一下。

标签: c# loops infinite-loop


【解决方案1】:

使用外部资源甚至滥用接口等工具来创建无限循环非常简单。

例如:

  public interface INumbers
    {
        int GetNumber(int arg);
    }
    public class StaticNumber : INumbers
    {
        public int GetNumber(int arg)
        {
            return 1;
        }
    }
    public void DoStuff(INumbers num)
    {
        int i = 42;
        while ((i = num.GetNumber(i)) != 0)
        {
            ;
        }
    }

然后是一个简单的

Action action = () => DoStuff(new StaticNumber());

【讨论】:

    【解决方案2】:

    Jon 所指的内容在规范的第 8.1 节中有所描述。编译器只能检测到非常简单的无限循环,例如:

    while(true) { if (0 != 0) return 123; }
    

    编译器足够聪明,可以看到永远不会到达返回值,因此循环会永远运行。这是合法的,虽然很疯狂,说:

    int M() { while(true) { } }
    

    因为虽然没有返回int的路径,但也没有返回而不返回int的路径!

    编译器不够聪明,无法找到其他类型的无限循环。例如:

    int x = 123;
    while(true) { if (x * 0 != 0) break; }
    

    这显然是一个无限循环。但是编译器不知道这一点。编译器说“好吧,也许有一些 x 的值,其中 x * 0 不为零,所以中断是可以到达的,所以这不是一个无限循环”。你我都知道这是不可能的,因为我们知道数学,但编译器不知道。

    如果您想了解详细信息,请阅读第 8.1 节。

    【讨论】:

    • 我实际上不记得写过这个 - 这表明脚注是由于你的影响:)
    • @Jon:您最初写的是“当然,抛出异常的代码路径不需要返回值”。我注意到可检测到的无限循环也算作无法到达的端点。
    • 是的——这似乎是我们每个人都想出的更详细的层次:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    • 2014-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    相关资源
    最近更新 更多