Home > database >  Goto statement in filesystem exception handling
Goto statement in filesystem exception handling

Time:11-13

save:
try
{
    s.Save();
}
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
{
    FSErrorDialog fsError = new(ex, FSVerb.Access, new FileInfo(path), Button.Retry, Button.Ignore);
    if (fsError.ShowDialog().ClickedButton == Button.Retry)
    {
        goto save;
    }
}

The Save() method saves the object to the disk. If an exogenous exception occurs, the user is prompted to retry the operation to avoid loosing unsaved data.

I know I could use a while (true) loop with break statements but I think the goto approach is more readable. It also saves an indentation level.

I am scared of using goto.

Is this a legitimate use of goto statements?

CodePudding user response:

I would suggest declaring a boolean to track if you should retry. That way you can use a do/while loop:

bool shouldRetry;
do
{
    try
    {
        s.Save();
        shouldRetry = false;
    }
    catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
    {
        FSErrorDialog fsError = new(ex, FSVerb.Access, new FileInfo(AppDirectory.Scripts.Join(s.FilePath)), Button.Retry, Button.Ignore);
        shouldRetry = fsError.ShowDialog().ClickedButton == Button.Retry;
    }
}
while (shouldRetry);

To address the "more readable" aspect that you mentioned in the question, I think this is more readable for 2 reasons:

  1. We're using something that exists explicitly as a loop, so it's clear from the beginning that looping is possible. You don't need to find the goto to work out that it loops.
  2. The variable name shouldRetry makes it abundantly clear why we are looping: because we need to retry.

CodePudding user response:

I suggest infinite loop; we loop until either we have no exception or when we decide to stop our attempts:

while (true) {
  try {
    s.Save();

    break; // No more looping (success)
  }
  catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) {
    FSErrorDialog fsError = new(ex, FSVerb.Access, new FileInfo(path), Button.Retry, Button.Ignore);
    
    if (fsError.ShowDialog().ClickedButton != Button.Retry)
      break; // No more looping (no more tries)  
  }
}
  • Related