c# - 什么是语句的不可到达端点(unreachable endpoint)?

标签 c#

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

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

  • If D has a non-void return type and the body of F is a statement block, when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid statement block (wrt §8.2) with a non-reachable end point in which each return statement specifies an expression that is implicitly convertible to the return type of D.

后面的规范我们可以看到

  • 8.1 End points and reachability

    Every statement has an end point. In intuitive terms, the end point of a statement is the location that immediately follows the statement. The execution rules for composite statements (statements that contain embedded statements) specify the action that is taken when control reaches the end point of an embedded statement. For example, when control reaches the end point of a statement in a block, control is transferred to the next statement in the block.
    ...

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

最佳答案

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 或 property getter 等)不得有可到达的终点。第三,如果一个方法有一个可达的终点并且它有一个out参数,那么这个参数必须在终点明确赋值。

关于c# - 什么是语句的不可到达端点(unreachable endpoint)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15168072/

相关文章:

c# - 直接通过返回码声明和初始化之间有什么区别吗?

c# - 关于在 C# 中正确使用 Task 的问题

c# - DataGridView 中的数据关系

c# - DLL 中的 Unity C# 脚本

c# - 列出两个日期之间的月份

c# - 使用命令行参数安装 IIS8

c# - 带有从数据库检索的选项的对话框

c# - .net mvc5 应用程序在实例化 View 模型时偶尔会无明显原因地因 ..ctor 引用而崩溃

c# - 更新安装

c# - CaSTLe 未解析所有已注册的组件