Steve Wellens

Programming in the .Net environment

Sponsors

Links

Why goto Still Exists in C#

Developers, Software Engineers, and Programmers are logical, rational, reasonable people right? Sure they are…until you disagree with something they believe in. Then they can become the most enflamed, outraged, foaming-at-the-mouth, intolerant, lunatics you've ever had the pleasure of meeting.

Take for instance the goto command. It can create emotions as intense as those raised during the ancient 'tabs versus spaces' debates or whether or not curly braces should be aligned in columns. (For the record, developers who use tabs and don't line up curly braces also kick puppies and do not practice good hygiene).

You can program for years and never use a goto. However, there are times when a goto can make the code simpler and that…is a very good thing.

Here's a scenario: You are working on a multi-threaded real-time program. You can't use the debugger because stepping through the code would mess up the timings and interactions between the threads. You also need something to help diagnose problems in the field.  A runtime log that can be turned on and off is used. The requirement is that every function will log its entry and exit point. That way if something goes wrong, the log will show what function failed and where it failed.

In one area of the program, you need to perform several steps in sequence. If any step fails, the remaining steps must not execute.

Here's the first attempt:  

// Do Process using nested if statements
void DoProcess1()
{
    LOG("DoProcess Started...");
 
    if (Step1() == true)
        if (Step2() == true)
            if (Step3() == true)
                if (Step4() == true)
                    if (Step5() == true)
                        if (Step6() == true)
                            Step7();
 
    LOG("DoProcess Finished");
}

Sure it works but getting code to work is only the first step. Creating clear, maintainable code is the goal. If the code can be simplified, you are not done.

Second attempt, use a flag variable:

// Do Process using a success flag
void DoProcess2()
{
    LOG("DoProcess Started...");
 
    bool Success;
 
    Success = Step1();
    if (Success == true)
        Success = Step2();
    if (Success == true)
        Success = Step3();
    if (Success == true)
        Success = Step4();
    if (Success == true)
        Success = Step5();
    if (Success == true)
        Success = Step6();
    if (Success == true)
        Success = Step7();
 
    LOG("DoProcess Finished");
}

That's better but it can be simplified further:

Third attempt with goto:

// DoProcess using goto
void DoProcess3()
{
    LOG("DoProcess Started...");
 
    if (Step1() == false)
        goto EXIT;
    if (Step2() == false)
        goto EXIT;
    if (Step3() == false)
        goto EXIT;
    if (Step4() == false)
        goto EXIT;
    if (Step5() == false)
        goto EXIT;
    if (Step6() == false)
        goto EXIT;
    if (Step7() == false)
        goto EXIT;
 
EXIT:
    LOG("DoProcess Finished");
}

The creation, assigning and checking of a variable has been eliminated. It also runs faster but the speed improvement is insignificant and not a reason for using a goto.

The example is trivial, however in real life, being able to jump to the end of complicated functions can dramatically reduce the complexity of code.

Before you disagree with the inclusion of the goto in the C# language, remember you are disagreeing with the people who created the language. You are also disagreeing with Steve McConnel the author of "Code Complete". Here's his chapter on gotos.

In my career, I've only used a goto once and I had to present the code to a code-review group of four developers. When I showed the code with and without the goto, they unanimously agreed without any discussion that goto was…the way to go. Pun intended.

I hope someone finds this helpful.

[Update: July 3, 2009]

Here are two more examples of when a goto is helpful. The first is from Charles Petzold’s book “.Net Book Zero” a free pdf book available at http://www.charlespetzold.com/

A switch “fall through” is illegal in C# (this causes a compiler error):

switch (a) 
{ 
    case 3: 
        b = 7; 
    case 4: 
        c = 3; 
        break; 
    default: 
        b = 2; 
        c = 4; 
        break; 
}

To get it to work you can use a goto:

switch (a) 
{ 
    case 3: 
        b = 7;
        goto case 4;
    case 4: 
        c = 3; 
        break; 
    default: 
        b = 2; 
        c = 4; 
        break; 
}
 

This example shows better how to cleanly get out of nested loops/code.  The task is to search a three dimensional array and check for a null value:

bool GetData()
{
    String[,,] Data = new String[5, 5, 5];
 
    // ....code to fill in array here
 
    for (int x = 0; x < 5; x++)
    {
        for (int y = 0; y < 5; y++)
        {
            for (int z = 0; z < 5; z++)
            {
                if (Data[x, y, z] == null)
                    goto NULL_FOUND;
            }
        }
    }
 
    return true;
 
NULL_FOUND:
    Response.Write("Invalid Data");
    return false;
}

Steve Wellens

Posted: Jun 01 2009, 01:36 PM by SGWellens | with 27 comment(s) |
Filed under: , ,

Comments

Koolraaga said:

I have one question about this... How is Goto internally implemented ? Would it not be a Jump Statement?

Using and not using goto is a Tradeoff between "Developer Readability" and may be "performance".

# June 1, 2009 8:51 PM

SGWellens said:

goto maps directly to an assembly instruction: jmp.

The compiler is better at optimizing than us mere human beings so the main concern is "Developer Readability".

Programming 1001:  It's the maintenance.

# June 1, 2009 10:23 PM

Reverse Cowgirl said:

if (Step1() && Step2() && Step3() && Step4() && Step5() && Step6() && Step7())

LOG("DoProcess Finished");

even more efficient.

# June 2, 2009 3:12 AM

Andrew Davey said:

In this example you could use the && operator because it will short circuit.

Step1() && Step2() && Step3() ... etc

Of course, there are still times when goto could be useful.

# June 2, 2009 4:16 AM

Rik Hemsley said:

You could inject your logging using an IoC framework, but anyway, it's easy to lose the goto:

void DoProcess3()

{

   LOG("DoProcess Started...");

   Step1()

   && Step2()

   && Step3()

   && Step4()

   && Step5()

   && Step6()

   && Step7()

   ;

   LOG("DoProcess Finished");

}

# June 2, 2009 5:46 AM

Jacob Stanley said:

What about:

// DoProcess using finally

void DoProcess4()

{

   LOG("DoProcess Started...");

   try

   {

       if (Step1() == false)

           return;

       if (Step2() == false)

           return;

       if (Step3() == false)

           return;

       if (Step4() == false)

           return;

       if (Step5() == false)

           return;

       if (Step6() == false)

           return;

       if (Step7() == false)

           return;

   }

   finally

   {

       LOG("DoProcess Finished");

   }

}

or

// DoProcess using Action

void DoProcess4()

{

   LOG("DoProcess Started...");

   Action[] actions =

   {

       Step1,

       Step2,

       Step3,

       Step4,

       Step5,

       Step6,

       Step7,

   };

   foreach (Action action in actions)

   {

       if (action() == false)

       {

           break;

       }

   }

   LOG("DoProcess Finished");

}

# June 2, 2009 5:58 AM

JeroenH said:

Aside from the fact that you probably want to solve the requirement by using some AOP solution, you don't really need goto in this case. What about:

void DoProcess()

{

LOG("DoProcess started");

 try

 {

   if (!Step1()) return;

   if (!Step2()) return;

   if (!Step3()) return;

 }

 finally

 {

   LOG("Do Process finished")

 }

}

# June 2, 2009 6:02 AM

Steve said:

define an array of Func_bool_ (the _ is for generics), and just loop through them while they return true, problem solved

# June 2, 2009 6:40 AM

Rinat Abdullin said:

Not that I agree to the design of hand-coding a sequence (a lot of valuable info is lost here), but have you tried replacing "goto EXIT;" with  a mere "return" and printing Log message in function calling DoProcess3?

# June 2, 2009 6:51 AM

Mike Perrin said:

that code is just crying out for another method

bool DoProcess()

{

   LOG("DoProcess Started...");

   DoProcessPrivate()

   LOG("DoProcess Finished");

}

void DoProcessPrivate()

{

   if (!Step1())

       return;

   if (!Step2())

       return;

   if (!Step3())

       return;

   if (!Step4())

       return;

   if (!Step5())

       return;

   if (!Step6())

       return;

   Step7()

}

# June 2, 2009 7:31 AM

willie said:

How about:

LOG("DoProcess Started...");

try

{

if(!Step1()) return;

if(!Step2()) return;

if(!Step3()) return;

if(!Step4()) return;

if(!Step5()) return;

if(!Step6()) return;

if(!Step7()) return;

}

finally

{

   LOG("DoProcess Finished");

}

# June 2, 2009 7:56 AM

Lee Friend said:

Goto is one of the oldest commands, very popular in the days before the event of OO and structured languages like COBOL.

However I only ever really used it in the 1980's/90's when old languages like BASIC had line numbers and you wanted to show how clever you were to non-programming friends e.g. 10 Print "Hello", 20 Goto 10 ...  

When I learned a second language - COBOL - my lecturer thwarted us to use it at every opportunity.  I haven't used it really since.  

However now seeing your third attempt example above, I do prefer the syntax over the other examples.

# June 2, 2009 8:52 AM

SGWellens said:

if (Step1() && Step2() && Step3() && Step4() && Step5() && Step6() && Step7())

That is dreadful, simply awful.  

How are you going to step into one of the functions with the debugger?

How are you going to set a breakpoint on a function?

One logical step per line of code should be a mandatory practise

LOG("DoProcess Started...");

  Step1()

  && Step2()

  && Step3()

  && Step4()

  && Step5()

  && Step6()

  && Step7()

  ;

  LOG("DoProcess Finished");

That is more interesting but in real life there would be code between the steps and your clever example wouldn't work.

The goal isn't to avoid using a goto...that's trivial.  The goal is to write the simplest possible code that is easy to maintain.

Please refer to the "Code Complete" chapter I provided a link to for larger examples.

# June 2, 2009 9:25 AM

SGWellens said:

I would have to say willie's example with the try...finally (no catch handler) and returns is the best alternative I've seen.

# June 2, 2009 10:50 AM

Steve Sheldon said:

I haven't used goto since MS-BASIC on CP/M back in the 1980s.

Whenever you think you need goto, think about it a bit and you'll come up with a way to write your function that is easier to read and doesn't require goto.

# June 2, 2009 11:15 AM

SGWellens said:

"Whenever you think you need goto, think about it a bit and you'll come up with a way to write your function that is easier to read and doesn't require goto."

No one "needs" to use goto.  No one ever stated that.

Avoiding goto for the sake of avoiding goto isn't rational.  Use the tool that best accomplishes the goal.  

# June 2, 2009 9:18 PM

SeanJA said:

"Avoiding goto for the sake of avoiding goto isn't rational.  Use the tool that best accomplishes the goal."

I would have to agree with @Mike Perrin on this one, it seems like you are going out of your way to use goto rather than thinking it through and doing a bit more abstraction. It is also more portable if you ever decide that there are problems that your language cannot solve and you need to re-write it in a different one (ie: Twitter's backend being re-written in scala) that does not have goto

# June 4, 2009 12:48 PM

lujan99 said:

void DoProcess3()

{

   LOG("DoProcess Started...");

   while(true){

     if ( !Step1())

         break;

     if ( !Step2())

         break;

     if ( !Step3())

         break;

     if ( !Step4())

         break;

     if ( !Step5())

         break;

     if ( !Step6())

         break;

     Step7();

         break;

       }

   LOG("DoProcess Finished");

}

# June 4, 2009 4:17 PM

SGWellens said:

"...it seems like you are going out of your way to use goto rather than thinking it through..."

My goodness, I don't see how anyone could come to such a conclusion.  Perhaps you'd better re-read the post and comments with more care.

You can also read the "Code Complete" article linked to in the post for more information.

# June 4, 2009 10:14 PM

SGWellens said:

To the other posters who have posted code that accomplishes the task without a goto:

Yes, the task can be accomplished without a goto.  I posted two examples myself.  But that is NOT the point.

The point is what is the BEST solution--the simplest, clearest, easiest to debug, easiest to understand solution.

The try-finally example is very good.  Except, it is a bit miseading in that it has return statements that do not really return.  try-finally is a "goto" with out the word goto.  

Well, it's getting late and...I've...got...to...GO.

# June 4, 2009 10:30 PM

Jack said:

A very late comment, the replies fit perfectly into the description of your first paragraph. There is really no point on spending a lot of time to find a potentially more complicated alternative to goto when the solution can be trivially implemented. I have found it a big waste of time to always try to prevent problems that have not yet happened.

  • Gotos do not make bad code; programmers do.
# December 9, 2009 11:25 PM

Alan said:

Yup, there are a few situation when a goto just makes sense. Thanks for injecting some rationality into this topic.

# January 11, 2010 12:29 AM

lol said:

Why does it really matter so much? Goto is a plain language statement, and very readable and obvious. There's nothing wrong with it. Useful sometimes, sometimes not. You guys act like it's bubonic plague or something, lol. I'd be interested to see each of these proposals compiled and examine the IL. Technically, you can write something two different ways and the compiler could emit the same thing. Use it if you like, or don't. :) Very simple!

# January 27, 2010 2:28 AM

Fero said:

I'm quite happy to have 'goto' in C#, although I use it rarely.  Sometimes if's, else's, and switch's just don't cut it.  Thanks for posting the article Steve.

# May 17, 2010 2:29 PM

Alan Churchill said:

No one has made this point which I think is valid.

If doing a code translation from one language to another (language A to C#, for example), you may need to emulate the other language to simplify the automatic code conversion. Other languages use gotos and there is normally no clean way to intelligently avoid it in a programmatic way. C# having a goto will help me do a converter.

# August 24, 2010 8:28 PM

Henrik said:

I couldn't agree with you more. Rightly used 'goto' can make your code more readable.

# January 24, 2011 2:43 PM

David said:

I am doing - read "trying" - a conversion from frotran to C#. The original fortran code has a billion gotos everywhere.

Observations made so far:

- Thank god C# supports goto, so I can start with a straight conversion;

- In some cases goto seems best. Program reads data from a file and goes back at multiple places. This could be done with flags, but goto makes it a lo simpler;

- Many goto statements make code EXTREMELY difficult to read.

I guess the question is not whether goto should be used or not, goto is there for a reason and if used judiciously it can be extremely useful. The problem arises when gotos are used to create spaghetti code.

# December 6, 2011 8:41 PM

Silvia said:

I liked this article, very much actually. I'm always around those programmers who don't like 'goto', and I'm a woman - nobody ever listens to my opinion :).

Now I know that I'm not the only one for whom it doesn't matter what you use - the result and understandable code is main goal. I don't use 'goto' much, but sometimes it's really helpful.

And I couldn't agree more with Kevin, who wrote that assembly language uses always 'goto'- I did in assembly some stuff a long time ago, and I now that for a fact. So I can't understand why 'goto' such a big deal (for not using it) for some of the programmers.

Thank you, Steve, for such a short but great article.

# February 6, 2012 4:51 AM

Paul M. Parks said:

I just encountered a handy situation that is solved rather elegantly with a goto. Yes, I could have done it without a goto, but it would have required more code and a flag variable, and it wouldn't have been as readable.

RETRY:

  try {

     int value = DoSomethingThatMightThrow();

     UseValue(value);

  }

  catch (DoSomethingException) {

     FixExceptionCondition();

     goto RETRY;

  }

A few things:

1. Yes, I know I could do this without a goto. I already stated that.

2. This is only useful in situations where it's expected that an exception might occur and where the exception can be handled properly with little fuss or runtime cost.

3. No, I'm not interested in discussing exceptions.

Thanks for the article. We need more level-headed discussions like this.

# April 2, 2012 2:55 PM