【发布时间】:2011-06-30 08:57:53
【问题描述】:
我有一个词法分析器/解析器对(几年前我抄袭了别人)。我将添加一些功能,并认为我会首先标准化包含多个 if/else if/else 的 while(true) 的使用与使用 goto 跳回到切换之前的开关。
(在火焰开始之前,我通常不使用 goto 作为它的邪恶等)
while(true) 和嵌套 switch 的问题是,break 只能跳出 switch,不能超出 while。
我在这里做了一些搜索,并看到了使用从开关内部返回的建议。虽然这在某些情况下会起作用,但在其他情况下,会在一段时间之后但在返回之前进行一些处理。在多个地方复制此代码并没有真正的吸引力。
我还可以引入一个布尔标志并在 while 语句中使用它来决定是否中断 while 但这也不吸引人,因为它会给代码增加噪音。
解析器中当前使用 if/else if/else 代替内部开关的方法可行,但如果可能的话,我确实偏爱开关。
一般来说,词法分析器代码似乎通过删除 while(true) 并在开关开始之前放置一个标签并使用 goto 继续循环来解决这个问题。这使得 break 意味着停止循环,老实说,这似乎是最干净的方式,但确实涉及可怕的 goto。
回到while(true),我还可以看到第三种方式。在 while(true) 之后使用标签,并让开关代码在循环结束时使用 goto 到达它。然后,Break 意味着退出开关但继续循环。
那么小组对此有何看法? goto 使用起来太可恶了吗?或者当只有一个标签可以跳转并减少缩进并产生其他清晰的代码时是否可以?解析器/词法分析器是否应该获得使用 goto 的特殊许可?
如果有帮助,我可以提供一些示例代码。
【问题讨论】:
-
Goto 并不邪恶。如果您正在编写状态机之类的代码,那么它的使用是完全合理的。等一下……解析器很可能是一个状态机。
-
确实,看看 Linux Kernel 源代码,goto 的位置非常整洁,代码很棒!
-
Linux 内核不同,因为它是用 C 编写的,除了“goto cleanup”之外,没有更简单/清晰/优雅的方式来处理错误和释放资源。此外,出于性能考虑,我们可能会使用一个长函数而不是将其拆分。这些都不适用于 C#,除了自动生成的代码外,没有理由在那里使用 goto。
-
@Simon:如果你自己回答了一个问题,请把你自己的答案标记为正确。