有人还在C#中使用,如果有的话,为什么?
我想知道是否任何人仍然使用C#中的“goto”关键字语法和可能的原因有这样做。
我倾向于认为任何导致读者跳出代码的言论都是不好的做法,但是想知道是否有任何可信的scheme来使用这种语法?
转到关键字定义
有一些(罕见的)goto可以提高可读性的情况。 实际上,你链接的文档列举了两个例子:
goto的一个常见用途是将控制权转移到特定的switch-case标签或switch语句中的默认标签。
goto语句对于深度嵌套循环也是有用的。
下面是后者的一个例子:
for (...) { for (...) { ... if (something) goto end_of_loop; } } end_of_loop:
当然,还有其他解决这个问题的方法,比如将代码重构成一个函数,使用它周围的虚拟块等等(详细请看这个问题 )。 作为一个侧面说明,Java语言devise者决定完全禁止goto ,而是引入一个带标签的break语句。
我记得这部分
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; }
参考这个
我在Eduasync中广泛使用它来显示在C#5中使用asynchronous方法时编译器为您生成的代码types。您将在迭代器块中看到相同的内容。
在“正常”代码,但我不记得我最后一次使用它…
goto非常适合打破许多循环,这些循环在break的时候不会很好(比如在错误条件下),Kragen说goto被编译器用来生成switch语句和一些其他的东西。
编译器在各种生成的代码中使用goto
语句,例如在生成的迭代器块types(使用yield return
关键字生成的时候生成) – 我非常肯定生成的XML序列化types在某处也有一些goto
语句。
请参阅迭代器块实现细节:自动生成的状态机了解C#编译器处理此问题的原因/方式的更多详细信息。
除了生成的代码之外,在正常代码中使用goto
语句没有什么好的理由 – 它使得代码更难理解,结果更容易出错。 另一方面,在这样的生成代码中使用goto
语句可以简化生成过程,并且通常很好,因为没有人会读取(或修改)生成的代码,并且不会因机器正在写入而出错。
请参阅Go-to语句 ,该语句被认为对反对goto
的争论是有害的 ,也是一段经典的编程历史。
我不记得曾经使用过goto
。 但是也许它改善了你永远不想退出的永久循环的意图(不break
,但你仍然可以return
或throw
):
forever: { // ... goto forever; }
再一次,一个简单的while (true)
就足够了…
另外,你也可以在你想要循环的第一个迭代在循环中间开始的情况下使用: 在这里看一个例子。
处理器实现了至less一个跳转指令 ,我确定很多语句使用它们的实现或解释。
使用第三代或第四代语言的好处之一就是这些物理细节是从我们这里抽象出来的。 虽然我们应该留意抽象抽象的规律,但我认为我们也应该使用我们的工具 ( 抱歉 )。 如果我正在编写代码,而且goto
似乎是个好主意,那么重构就是时候了。 结构化语言的目的是避免这些“跳跃”,并在我们的工程中创build一个逻辑stream程。
我应该避免使用break
但我不能忽视性能的好处。 但是,如果我有嵌套循环相互需要break
它是时间重构。
如果有人可以提出使用比重构好的goto
,我会很乐意收回我的答案。
我希望我没有犯这种冲向“ 自行车棚 ”的罪名。 就像Kragen所说的,对Dijkstra来说足够好的东西对我来说已经足够了。
例如,在从方法返回之前必须进行清理时,这是非常好的。
while (stream.Read(buffer, 0, 4) == 4) { // do smth with the 4 bytes read here if (stream.Read(buffer, 0, 4) != 4) goto CLOSE_STREAM_AND_RETURN; // do more stuff if (stream.Read(buffer, 0, 4) != 4) goto CLOSE_STREAM_AND_RETURN; // more stuff } CLOSE_STREAM_AND_RETURN: stream.Close();
启发: http : //eli.thegreenplace.net/2009/04/27/using-goto-for-error-handling-in-c/
我正在查看.net源代码,并在WebControl的ControlStyle属性中遇到了这个问题
public Style ControlStyle { get { if (this.controlStyle == null) { this.controlStyle = this.CreateControlStyle(); if (base.IsTrackingViewState) { this.controlStyle.TrackViewState(); } if (!this._webControlFlags[1]) { goto IL_4D; } this._webControlFlags.Clear(1); this.controlStyle.LoadViewState(null); } IL_4D: return this.controlStyle; } }
所以即使是微软也使用它
转到是永远不会更好。 并继续,打破(除了在开关/情况下),(多)返回,而抛出也应保持在最低限度。 你永远不想从巢循环的中间逃脱。 你总是希望循环控制语句拥有所有的循环控制。 缩进有信息,所有这些陈述都将这些信息扔掉。 你不妨把所有的缩进。