0

I usually fall into a situation where goto seems to be the best option to my mind. But I have read several times not to use it, and there is always an alternative. Now, I am trying something like this:-

    try{
            //Something that requires internet connectivity;
    }
     catch{
            //Show a message-Internet connectivity lost,and go back to try
    //-->FYI--Ignore "show message", because I am just appending this text to a  
    // textbox. So there won't be a problem of multiple ShowMessage Boxes.
      }

Now, the best option seems to me is to use goto in catch statement, but I am trying to avoid it. try is the first statement in a function, and if I recall that function, I am piling up stacks, so thats not a better option as well. What alternative can I take?

vish213
  • 748
  • 3
  • 12
  • 27
  • is it possible to create a function for this? – cprogcr Sep 19 '12 at 11:10
  • You mean everything inside try block? Yes the code is quite simple and I can create a function for it,,or maybe I am not getting your point? – vish213 Sep 19 '12 at 11:13
  • 3
    "But I have read several times not to use it" - Where did you read this? The quote from Edsger W. Dijkstra was about over use of `GOTO` in a specific language. – Oded Sep 19 '12 at 11:14
  • yes you got it right, then you call the function again. But the check the answers below too. They might offer a better alternative – cprogcr Sep 19 '12 at 11:15
  • @Oded: I read it in a book(Yashwant Kanetkar) of C, and since it was my first programming book,everything from it has just stuck to my mind(like if someone tells you ghost stories in childhood,they stuck forever). I clearly remember the line-"Avoid use of goto, they make programmer's life miserable" :-D. However it often makes mine simpler. – vish213 Sep 19 '12 at 11:19
  • Not all languages are made the same. In C, unconstrained use of `GOTO` could very well lead to problems. Used in moderation in C#, they can be helpful. – Oded Sep 19 '12 at 11:20
  • If you come to a point and `goto` ever the solution you come up with as being acceptable then you have done something wrong. The `catch` is what happen if there is an error, I can't think of any reason to use `goto`, at the very least a `catch` statement should reverse course in whatever caused the error if possible. In this simple example a message to the user to connect to the internet seems like the simple solution. This hardly requires a `goto` – Security Hound Sep 19 '12 at 12:22
  • @Ramhound : If there is no Internet Connectivity, I want to write message why application is delaying certain events. Then, I want application to GO BACK AND RETRY INTERNET CONNECTION,,i.e. to run try block again. Isn't goto useful here? Plus when I need user to enter a value for variable,(e.g. age), I run a check to see if its within limits(1 to 100 in this case). Now, if its not in limits, I love to simply put goto like this-- if(age not within limits){goto enterage;} ,,enterage: is where Console.Readline() for age is. – vish213 Sep 22 '12 at 09:19

3 Answers3

8

Use a while loop with a flag

var tryAgain = true;
while (tryAgain) 
{
    try
    {
        ...
        tryAgain = false;
    }
    catch (...)
    {
        tryAgain = ...
    }
}
James
  • 80,725
  • 18
  • 167
  • 237
  • 1
    Use a while loop with a flag? Seriously?! What if a serious error happens, like division by zero. The loop just turns into an infinite loop and the entire solution breaks! That just makes the problem difficult to diagnose. I'm downvoting this. – autistic May 08 '13 at 15:27
  • 1
    @undefinedbehaviour you would be catching a *specific* exception, you wouldn't catch *any* exception here, so if something did go wrong the exception would bubble up - just like you'd expect. – James May 08 '13 at 15:35
  • What do you think [this link](http://msmvps.com/blogs/peterritchie/archive/2007/06/22/performance-implications-of-try-catch-finally.aspx) suggests? – autistic May 08 '13 at 15:59
  • That link suggests that **under specific circumstances** you could lose out on some compiler optimizations, which could be milliseconds... – James May 08 '13 at 16:49
4

In this particular case there is nothing wrong with calling the same function recursively and keeping a counter with the number of times you've called it. Something like this (in pseudo code):

public void DoMyInternetThing(int numberOfAttemptsRemaining)
{
    try 
    {
         //do stuff
    }
    catch (ConnectionException) 
    {
        if (numberOfAttemptsRemaining <= 0)
            throw new SomethingBadHappenedException();

        DoMyInternetThing(numberOfAttemptsRemaining - 1);  
    }
}

As with anything recursive you need to ensure you structure it correctly, but this works nicely (I've used it myself) and it avoids your goto (which is not bad in itself, but use of it can lead to spaghetti or badly structured code).

slugster
  • 49,403
  • 14
  • 95
  • 145
  • i think you meant --numberOfAttemptsRemaining, as your code would lead to a stackoverflow after enough retries or better use numberOfAttemptsRemaining-1 instead. – BlueM Sep 19 '12 at 11:17
  • 1
    For readability, I'd opt for `numberOfAttemptsRemaining - 1`, since it is easy to make mistakes and you're changing the input argument of the method, without having a real need to. Still +1 for your solution. – Steven Sep 19 '12 at 11:33
  • @Steven The `--numberOfAttemptsRemaining` worked for the structure I had, it avoided popping out on the throw then recursing back in because the local copy of `numberOfAttemptsRemaining` hadn't changed. In any case I've restructured it to make it more readable (although that means throwing a new exception rather than just using `throw`). – slugster Sep 19 '12 at 12:13
  • 1
    @slugster: IMO, your answer should have been marked as answer. – Steven Sep 19 '12 at 12:16
  • @Steven the OP doesn't mention anything with regards to maximum number of attempts. Therefore, I would disagree that it "*should have been marked as answer*" because it doesn't solve the OPs problem out of the box. I am not knocking this solution at all as I can see where it would be handy. However, it's slightly inflexible as it gives the user no control over whether they want to re-try or not, it happens automatically. – James Sep 19 '12 at 12:24
  • @James Inserting/showing a message box is not a problem with this, it can simply be inserted in the right place in the catch. I do agree that this isn't a good approach for endless retries though - not that you should retry endlessly. Arguably you should retry a number of times, then exit to the caller and allow the caller to notify the user and offer the chance to retry. – slugster Sep 19 '12 at 12:35
  • @slugster "*not that you should retry endlessly*" - Programmatically, I would agree. However, if it's a decision presented to the user then there is no reason why you should stop the user from doing so. A good example of this is attempting to delete a file that no longer exists, you can hit *Try Again* until the cows come home... – James Sep 19 '12 at 12:43
2

If you want to try again, wrap your try-catch in a do-while loop.

zmbq
  • 38,013
  • 14
  • 101
  • 171
  • what goes inside while?? Like set a varible to true inside catch block and test it inside while? Ya that seems to be quite a good option. – vish213 Sep 19 '12 at 11:13