为什么不建议使用此'goto'语句?

  • 本文关键字:goto 语句 c# goto
  • 更新时间 :
  • 英文 :


我们在公司内部就是否应该在项目中使用goto语句展开了一场大辩论。我个人发现它为以下需要重试web服务调用的场景增加了清晰度。

const string primaryWebServiceUrl = "https://example.com/Server.asmx";
const string secondaryWebServiceUrl = "https://example2.com/Server.asmx";
using (var ws = new Server())
{
ws.Url = primaryWebServiceUrl;
start:
try
{
wsAction?.Invoke(ws);
}
catch
{
if (ws.Url == secondaryWebServiceUrl)
throw;
ws.Url = secondaryWebServiceUrl;
goto start;
}
}

我认为在这种情况下添加一个循环会牺牲代码的清晰度,并且我发现仅仅因为有Retry逻辑而引用Polly是一种过分的做法。

编辑:由于每个人都说不建议在这里使用goto语句,我想了解更多关于为什么不建议使用goto以及它可能产生的有害影响的信息。在我看来,这增加了清晰度,但我可以理解,如果使用不当,goto语句的解除效果可能是负面的,但在上面提供的示例中,为什么不建议使用goto方法?

这是有效,但不推荐可读性更强的实现类似于

using (var ws = new Server()) {
ws.Url = primaryWebServiceUrl;
// Keep doing ...
while (true) {
try {
wsAction?.Invoke(ws);
// ...until Invoke succeeds
break; 
}
catch { //TODO: put expected Exception type here
// Something is very wrong; rethrow the exception and leave the routine 
if (ws.Url == secondaryWebServiceUrl)
throw;
ws.Url = secondaryWebServiceUrl;
} 
}
}

或者更好(尤其是如果我们想有很多url(-感谢Panagiotis Kanavos的想法:

string[] urls = new string[] {
"https://example.com/Server.asmx",
"https://example2.com/Server.asmx",
"https://example3.com/Server.asmx", 
...
"https://example123.com/Server.asmx", 
};
using (var ws = new Server()) {
// Try each url from urls...
for (int i = 0; i < urls.Length; ++i) {
try {
ws.Url = urls[i];
wsAction?.Invoke(ws);
// ... until success 
break;  
}
catch {
// The last url failed; rethrow the error
if (i >= urls.Length - 1)
throw; 
}  
} 
} 

goto在switch语句之外的任何地方都被认为是非常糟糕的做法。有许多更好的构造。

您可以将try/catch逻辑移动到一个方法,并进行循环检查结果(可能为true/false(,然后继续调用该方法,而不是使用goto

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/goto

此链接明确提到切换和退出深度嵌套循环。这两种情况都不适用于此。

最新更新