什么是语句的不可到达终点(不可达端点)?
灵感来自这个问题的答案
C#中的开关是空的情况还是下一个非空的?
该术语的唯一出现在C#语言规范的§6.5中
- 如果
D
具有非void返回类型且F
的主体是语句块,则当F
每个参数被赋予D
相应参数的类型时,F
的主体是有效语句块(wrt§8.2),一个不可到达的端点 ,其中每个return语句指定一个可隐式转换为D
的返回类型的表达式。
我们可以看到规范中的后者
8.1终点和可达性
每个陈述都有一个终点 。 直观地说,语句的结束点是紧跟语句的位置。 复合语句(包含嵌入语句的语句)的执行规则指定控件到达嵌入语句的结束点时所采取的操作。 例如,当控件到达块中语句的结束点时,控制权将转移到块中的下一个语句。
…
我们可能对此有所了解。 但是,我用Google搜索并发现没有直接解释不可到达的端点 。 因为Stack Overflow是一个Q&A网站,我认为如果有一个更简单,更直观的解释,可以轻松搜索和理解这个术语对程序员尤其是那些不是母语为英语的人有用。
Ben的回答很好地理解了它。 为了更精确,终点:
- 打破
- 继续
- 去
- 返回
- 扔
语句无法访问。 这些语句中的每一个都在“结束之前”将控制转移到其他地方,因此语句的“终点”永远不会被命中。 将其与以下语句进行比较:
- Console.WriteLine();
- 我++;
等等,将控制转移到下一个语句。
循环提出了一个有趣的挑战:
while(x) { M(); }
这基本上与:
BEGIN: if (!x) goto END; { M(); } goto BEGIN; END: ;
所以端点是可达的。 但
while(true) { M(); }
可以优化为:
BEGIN: { M(); } goto BEGIN;
由于现在无法“到达目的地”,因此该语句被认为具有无法到达的终点。 要么永远循环,要么M()永远不会返回,要么M()抛出; 无论哪种方式,都没有达到声明的终点。
确定可达性的确切规则比这个草图要复杂一些,但是这可以让你对它们有所了解。 (我喜欢让人们看看他们是否掌握了可达性的挑战是:编写一个程序,该程序具有可访问的goto语句但相应的标记语句是无法访问的.Tricky!)
这些规则在许多地方使用。 立即想到三个:首先,开关部分必须没有可达到的终点。 其次,非void的方法(或lambda或属性getter等)必须没有可到达的端点。 第三,如果方法具有可到达的终点并且它具有out参数,则必须在结束点明确指定参数。
简单来说,当且仅当语句完成而不执行分支(控制转移)时才会到达端点。
因此,当块退出块时,块存在一个不可达的端点
- 无条件的,或
- 存在于所有可能的执行路径中。