Does Anyone Still Use [Goto] in C# and If So Why

Does anyone still use [goto] in C# and if so why?

There are some (rare) cases where goto can actually improve readability. In fact, the documentation you linked to lists two examples:

A common use of goto is to transfer control to a specific switch-case label or the default label in a switch statement.

The goto statement is also useful to get out of deeply nested loops.

Here's an example for the latter one:

for (...) {
for (...) {
...
if (something)
goto end_of_loop;
}
}

end_of_loop:

Of course, there are other ways around this problem as well, such as refactoring the code into a function, using a dummy block around it, etc. (see this question for details). As a side note, the Java language designers decided to ban goto completely and introduce a labeled break statement instead.

Is there ever a reason to use goto in modern .NET code?

Reflector is not perfect. The actual code of this method is available from the Reference Source. It is located in ndp\fx\src\xsp\system\web\security\admembershipprovider.cs:

        if( passwordStrengthRegularExpression != null )
{
passwordStrengthRegularExpression = passwordStrengthRegularExpression.Trim();
if( passwordStrengthRegularExpression.Length != 0 )
{
try
{
Regex regex = new Regex( passwordStrengthRegularExpression );
}
catch( ArgumentException e )
{
throw new ProviderException( e.Message, e );
}
}
}
else
{
passwordStrengthRegularExpression = string.Empty;
}

Note how it failed to detect the last else clause and compensated for it with a goto. It is almost certainly tripped-up by the try/catch blocks inside the if() statements.

Clearly you'll want to favor the actual source code instead of the decompiled version. The comments in themselves are quite helpful and you can count on the source being accurate. Well, mostly accurate, there's some minor damage from a buggy post-processing tool that removed the names of the Microsoft programmers. Identifiers are sometimes replaced by dashes and the code is repeated twice. You can download the source here.

Is using a 'goto' statement bad?

EDIT:

How bad is the goto statement really, and why?

It depends on the exact situation. I can't remember any time where I found it made the code more readable than refactoring. It also depends on your personal view of readability - some people dislike it more than others, as is clear from the other answers. (As a point of interest, it's widely used in generated code - all of the async/await code in C# 5 is based on effectively a lot of gotos).

The problem is that situations where goto tends to be used tend to be the kind of situations where refactoring aids things anyway - whereas goto sticks with a solution which becomes harder to follow as the code gets more complicated.

Is there a more effective way to break the main loop than using the 'goto' statement?

Absolutely. Extract your method out into a separate function:

while (ProcessValues(...))
{
// Body left deliberately empty
}

...

private bool ProcessValues()
{
for (int i = 0; i < 15; i++)
{
// Do something
return false;
}
return true;
}

I generally prefer doing this over introducing an extra local variable to keep track of "have I finished" - although that will work too, of course.

Does C# have runtime-assigned goto?

Please note that C# example code below is intended specifically for use as the output format of a BASIC-to-C# compiler. Anyone who writes “real” C# code like this shall have their programming license revoked.

BASIC's GOTO statement can be implemented using “tail call pessimization”: Transform every GOTO X to GOSUB X:RETURN.

You can then render your entire BASIC program as one giant Gosub(int lineNumber) function, using a switch statement with a case block for each line number, with a Main function that simply GOSUBs to the lowest line number.

So, for example, the BASIC program:

10 PRINT "Enter an integer: ";
20 INPUT N%
30 IF N% MOD 2 = 0 THEN GOTO 60
40 PRINT N%;" is odd."
50 GOTO 70
60 PRINT N%;" is even."
70 PRINT "Goodbye."

can be converted line-by-line into a C# program like this:

using System;

static class Program
{
// BASIC variables are always global and zero-initialized.
static int n_int = 0;

static void Gosub(int lineNumber)
{
switch (lineNumber)
{
case 10: // 10 PRINT "Enter an integer: ";N%
Console.Write("Enter an integer: ");
// By default, the end of each line falls thru to next line number
goto case 20;
case 20: // 20 INPUT N%
n_int = int.Parse(Console.ReadLine());
goto case 30;
case 30: // 30 IF N% MOD 2 = 0 THEN GOTO 60
if (n_int % 2 == 0)
{
Gosub(60);
return;
}
goto case 40;
case 40: // 40 PRINT N%;" is odd."
Console.WriteLine("{0} is odd.", n_int);
goto case 50;
case 50: // 50 GOTO 70
Gosub(70);
return;
case 60: // 60 PRINT N%;" is even."
Console.WriteLine("{0} is even.", n_int);
goto case 70;
case 70: // 70 PRINT "Goodbye."
Console.WriteLine("Goodbye.");
// Falling off the end of the program exits it.
return;
}
}

static void Main()
{
Gosub(10);
}
}

When you have a literal line number like this, you can optimize Gosub(X); return; to goto case X;. However, the function call approach allows the line number to be an arbitrary expression, which C#'s goto case does not.

The converted code obviously isn't very maintainable, but it does compile and run.

Edit: Apparently, the C# compiler doesn't guarantee tail call optimization, which may cause a stack overflow for long or infinite loops. However, you can perform this optimization manually by re-assigning the lineNumber parameter and jumping back to the start of the switch statement, like this:

using System;

static class Program
{
// BASIC variables are always global and zero-initialized.
static int n_int = 0;

static void Gosub(int lineNumber)
{
START:
switch (lineNumber)
{
case 10: // 10 PRINT "Enter an integer: ";N%
Console.Write("Enter an integer: ");
// By default, the end of each line falls thru to next line number
goto case 20;
case 20: // 20 INPUT N%
n_int = int.Parse(Console.ReadLine());
goto case 30;
case 30: // 30 IF N% MOD 2 = 0 THEN GOTO 60
if (n_int % 2 == 0)
{
lineNumber = 60;
goto START;
}
goto case 40;
case 40: // 40 PRINT N%;" is odd."
Console.WriteLine("{0} is odd.", n_int);
goto case 50;
case 50: // 50 GOTO 70
lineNumber = 70;
goto START;
case 60: // 60 PRINT N%;" is even."
Console.WriteLine("{0} is even.", n_int);
goto case 70;
case 70: // 70 PRINT "Goodbye."
Console.WriteLine("Goodbye.");
// Falling off the end of the program exits it.
return;
}
}

static void Main()
{
Gosub(10);
Console.ReadKey();
}
}

As in the previous example, a constant GOTO target can be optimized into a single goto case statement.

Are there any legitimate use-cases for goto in a language that supports loops and functions?

There are a few reasons for using the "goto" statement that I'm aware of (some have spoken to this already):

Cleanly exiting a function

Often in a function, you may allocate resources and need to exit in multiple places. Programmers can simplify their code by putting the resource cleanup code at the end of the function, and all "exit points" of the function would goto the cleanup label. This way, you don't have to write cleanup code at every "exit point" of the function.

Exiting nested loops

If you're in a nested loop and need to break out of all loops, a goto can make this much cleaner and simpler than break statements and if-checks.

Low-level performance improvements

This is only valid in perf-critical code, but goto statements execute very quickly and can give you a boost when moving through a function. This is a double-edged sword, however, because a compiler typically cannot optimize code that contains gotos.

Note that in all these examples, gotos are restricted to the scope of a single function.

Should I use goto statement?

It sounds like you really want a loop. I'd write it as:

bool successful = false;
while (!successful)
{
try
{
while(true)
{
// I hope you have a break in here somewhere...
}
successful = true;
}
catch (...)
{
...
}
}

You might want to use a do/while loop instead; I tend to prefer straight while loops, but it's a personal preference and I can see how it might be more appropriate here.

I wouldn't use goto though. It tends to make the code harder to follow.

Of course if you really want an infinite loop, just put the try/catch inside the loop:

while (true)
{
try
{
...
}
catch (Exception)
{
...
}
}

Is this a good use of the goto statement?

No - use return instead. Why force someone reading your code to skip to an exit point and then return? You know everything you need to do at this point - so the clearest solution is to return, IMO.

The "don't have multiple exit points" idea was appropriate in languages where you'd need to do things like cleanup on the exit of a function, but between garbage collection and finally blocks, it's pointless and counterproductive in C#.

What do you want to do if the condition is met? Return from the method. So make your code say that. Wherever you can make the code say exactly what you mean, that's a good thing. Don't make it more complicated than it needs to be.

I'm assuming your real situation is more complicated than just these conditions, otherwise I'd use something like Marcelo's answer, but probably written as:

return !(condition1 || condition2 || condition3);

What is the better pratice: duplicate code or use goto statement?


Example 1 pros and cons


+ Common structure
+ Simple to understand logic
- More lines of code
- Code repetition

Example 2 pros and cons


+ Fewer lines of code
+ No code repetition
- It complicates logic
- It is not commonly used in production code

Bottom line

I would prefer example 1, because, in this particular instance, the savings are minimal, but the logic gets more complicated. Goto, arguably, increases the chances of a bug if more people starts working on the same code, as difficulty of code increases. Let's have a look at this embarrassing bug. Had developers not used a goto, there wouldn't be such a problem!

Bonus points

  • You can use enums for case selection, so case 3: => case CarPart.SteeringWheel
  • make sure each case has a break;
  • make sure there is a default case
  • consider using polymorphism and inheritance instead of a switch case

    ICarPart part1 = new SteeringWheel();
    ICarPart part2= new Mirror();
    var parts = new List<ICarPart>() {part1, part2};

    // now call your original method on the parts
    // no more need for a switch case

Is the goto statement slow in c#?


is goto slower than other flow control constructs?

No. All the other flow control constructs are basically goto anyway.

Why not GOTO Statement?

At least for some programming languages (none of which I'm the designer of, obviously) like C and C++, I imagine it's there because it

  1. Closely models what the hardware really can do, which is kind of the goal in these languages.
  2. Is sometimes actually useful and better than more "structured" approaches.

The most common example of when goto is often considered good is when doing nested error/resource management in C. See for instance the Linux kernel, a fairly large and successful C project which uses goto for this purpose.



Related Topics



Leave a reply



Submit