We're having a big debate in the company whether or not goto
statements should be used at all in projects. I personally find it to be adding clarity for the following scenario where I need to retry a web service call.
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;
}
}
I believe that adding a loop in this case sacrifices code clarity and I find it to be an overkill to reference Polly just for having Retry logic.
Edit: Since everyone is saying that it's not recommended to use a goto statement here I'd like to learn more about why this is not recommended and what detrimental effects it can have. In my opinion this adds clarity but I can understand that the goto statement unwinding effect can be negative if not used correctly but in the example provided above, why the goto approach is not recommended?
It's valid, but not recommended; a more readable implementation is something like this
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;
}
}
}
Or even better (especially if we want to have many urls) - thank to Panagiotis Kanavos for the idea:
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;
}
}
}