在公司中,我们是否在项目中完全使用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方法?
答案 0 :(得分:2)
这是有效,但不推荐; 更易读的实现是这样的
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;
}
}
}
甚至更好(尤其是如果我们想拥有许多网址)-感谢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;
}
}
}
答案 1 :(得分:0)
在switch语句之外的任何地方,goto都被认为是非常糟糕的做法。有很多更好的构造。
您可以将try / catch逻辑移至某个方法,并循环检查结果(可能为true / false),然后继续调用该方法-而不是使用goto
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/goto
此链接明确提到切换和退出深嵌套循环。这两种情况均不适用。