有人还在C#中使用[goto],如果是这样,为什么?

时间:2011-07-01 08:57:15

标签: c# .net coding-style goto

我想知道是否有人仍然在C#中使用“goto”关键字语法,以及可能的原因。

我倾向于查看导致读者跳过代码的任何语句作为不好的做法,但是想知道是否有任何可靠的方案来使用这样的语法?

Goto Keyword Definition

8 个答案:

答案 0 :(得分:84)

有一些(罕见的)goto实际上可以提高可读性的情况。实际上,您链接的文档列出了两个示例:

  

goto的一个常见用途是将控制转移到特定的switch-case标签或switch语句中的默认标签。

     

goto语句对于摆脱深层嵌套循环也很有用。

以下是后一个例子:

for (...) {
    for (...) {
        ...
        if (something)
            goto end_of_loop;
    }
}

end_of_loop:

当然,还有其他方法可以解决这个问题,例如将代码重构为函数,在其周围使用虚拟块等等(有关详细信息,请参阅this question)。作为旁注,Java语言设计者决定完全禁止转到,而是引入一个带有标记的break 语句。

答案 1 :(得分:60)

我记得这部分

switch (a)     
{ 
    case 3: 
        b = 7;
        // We want to drop through into case 4, but C# doesn't let us
    case 4: 
        c = 3;
        break; 
    default: 
        b = 2;
        c = 4;
        break; 
}

这样的事情

switch (a)     
{
    case 3: 
        b = 7;
        goto case 4;    
    case 4: 
        c = 3;
        break;     
    default: 
        b = 2;
        c = 4;
        break;
}

参考This

答案 2 :(得分:21)

我在Eduasync中广泛使用它来显示编译器在C#5中使用异步方法时为您生成的代码类型。您会在迭代器块中看到相同的内容。

在“普通”代码中,我记不起上次使用它了......

答案 3 :(得分:8)

goto非常适合打破许多循环,其中break不能很好地工作(比如错误条件),并且正如Kragen所说,编译器使用goto来生成switch语句和其他一些东西。

答案 4 :(得分:6)

我不记得曾经使用goto。但是也许它改善了你真正永远不想退出的永久循环的意图(没有break,但你仍然可以returnthrow):< / p>

forever: {
  // ...
  goto forever;
}

然后,一个简单的while (true)就足够了......

此外,你可能在你希望循环的第一次迭代在循环中间开始的情况下使用:查看here作为示例。

答案 5 :(得分:5)

编译器在各种生成的代码中使用goto语句,例如在生成的迭代器块类型中(使用yield return关键字时生成) - 我很确定生成的XML序列化类型也是在那里也有一些goto陈述。

有关C#编译器处理此问题的原因/方式的详细信息,请参阅Iterator block implementation details: auto-generated state machines

除了生成的代码之外,没有充分的理由在普通代码中使用goto语句 - 它使代码更难理解,因此更容易出错。另一方面,在这样生成的代码中使用goto语句可以简化生成过程,并且通常很好,因为没有人会读取(或修改)生成的代码,因为机器不会出错正在写作。

请参阅Go-to statement considered harmful,了解针对goto的论据以及一段经典的编程历史。

答案 6 :(得分:2)

处理器实现至少一个jump instruction,我相信很多语句都会在实现或解释中使用它们。

使用3rd4th代语言的好处之一是这些物理细节都是从我们身上抽象出来的。虽然我们应该注意law of leaky abstraction我认为我们也应该使用tools as they are intended抱歉)。如果我正在编写代码并且goto似乎是一个好主意,那么现在是重构的时候了。结构化语言的目的是避免这些“跳跃”并在我们的工程中创建逻辑流程。

我应该避免使用break,但我不能忽视性能优势。但是,如果我有相互需要break的嵌套循环,则需要重构。

如果有人可以建议使用goto似乎比重构更好的话,我会很乐意撤回我的答案。

我希望我在这里赶到“bike shed”并不感到内疚。就像克拉根说的那样,Dijkstra足够好对我来说已经足够了。

答案 7 :(得分:-4)

Goto永远不会更好。并继续,中断(在switch / case中除外),(multiple)return,并且throw也应该保持在最小的最小值。你永远不想逃离巢循环的中间。您总是希望循环控制语句具有所有循环控制。缩进有信息,所有这些声明都会丢弃这些信息。你不妨拿出所有的缩进。