【问题标题】:What is a non-reachable end point(unreachable endpoint) of a statement?什么是语句的不可到达终点(unreachable endpoint)?
【发布时间】:2013-03-01 22:41:24
【问题描述】:

灵感来自这个问题的答案
Is empty case of switch in C# combined with the next non-empty one?

该术语的唯一出现在 C# 语言规范的 §6.5 中

  • 如果D有一个非void返回类型并且F的主体是一个语句块,当F的每个参数被赋予D中对应参数的类型时,@的主体987654326@ 是一个有效的语句块(wrt §8.2),带有一个不可到达的端点,其中每个返回语句都指定一个表达式,该表达式可以隐式转换为D

在规范的后面我们可以看到

  • 8.1 端点和可达性

    每个语句都有一个结束点。直观地说,语句的结束点是紧跟在语句之后的位置。复合语句(包含嵌入语句的语句)的执行规则指定当控制到达嵌入语句的终点时所采取的动作。例如,当控制到达块中语句的终点时,控制将转移到块中的下一条语句。
    ...

我们可能对此有所了解。但是,我搜索了一下,发现没有无法到达的端点的直接解释。因为 Stack Overflow 是一个问答网站,我认为如果有一个更简单、更直观的解释,可以很容易地搜索和理解这个术语,对程序员尤其是非英语母语的程序员会有帮助。

【问题讨论】:

    标签: c#


    【解决方案1】:

    Ben 的回答很好地说明了这一点。更准确地说,端点:

    • 打破
    • 继续
    • 转到
    • 返回
    • 投掷

    语句不可访问。这些语句中的每一个都在“结束之前”将控制权转移到其他地方,因此语句的“结束点”永远不会被击中。将其与以下语句进行比较:

    • Console.WriteLine();
    • i++;

    以此类推,将控制权转移到下一条语句。

    循环提出了一个有趣的挑战:

    while(x) { M(); }
    

    本质上是一样的:

    BEGIN: 
    if (!x) goto END;
    { M(); }
    goto BEGIN;
    END: ;
    

    所以端点是可达的。但是

    while(true) { M(); }
    

    可以优化为:

    BEGIN: 
    { M(); }
    goto BEGIN;
    

    由于现在没有办法“走到尽头”,所以这条语句被认为有一个无法到达的终点。这要么永远循环,要么 M() 永远不会返回,或者 M() 抛出;无论哪种方式,都不会到达语句的终点。

    确定可达性的确切规则比这个草图要复杂一些,但这让你对它们有所了解。 (我想给人们一个挑战,看看他们是否掌握了可达性:编写一个程序,它有一个可达的 goto 语句,但相应的标记语句是不可达的。棘手!)

    这些规则用于许多地方。立即想到的三个:首先,开关部分不能有可到达的端点。其次,非 void 的方法(或 lambda 或属性 getter 等)不得具有可到达的端点。第三,如果一个方法有一个可到达的端点,并且它有一个out参数,那么这个参数一定是在端点处明确赋值的。

    【讨论】:

    • 如果在这种情况下 goto 是可达的,那么标记的语句也是可达的。挑战在于提出一个可访问的 goto,它的目标标签是不可访问的。
    • @Brian:非常感谢!
    【解决方案2】:

    简单来说,当且仅当一条语句在没有执行分支(控制转移)的情况下完成时才到达端点。

    因此,当一个分支退出该块时,该块存在一个不可到达的端点

    1. 无条件,或
    2. 存在于所有可能的执行路径中。

    【讨论】:

      猜你喜欢
      • 2016-07-25
      • 2016-01-15
      • 2018-08-12
      • 1970-01-01
      • 2018-03-07
      • 2016-06-02
      • 1970-01-01
      • 2013-12-29
      • 1970-01-01
      相关资源
      最近更新 更多