C# Goto Loop Example

Goto keyword

Statements execute one after another. With the goto statement, though, we transfer control to a named label elsewhere in the method. The C# language provides the goto statement. Goto can be used to exit a deeply nested loop. As are many things, it is considered harmful.

Overview: This C# example page shows how to use the goto statement. It demonstrates loops.

Example

To start, we see exactly how you can use goto to exit a loop in the C# language. You can use code that does the same thing without goto, but would need a flag variable—usually a bool—to check.

Program that uses goto [C#]

using System;

class Program
{
    static void Main()
    {
	Console.WriteLine(M());
    }

    static int M()
    {
	int dummy = 0;
	for (int a = 0; a < 10; a++)
	{
	    for (int y = 0; y < 10; y++) // Run until condition.
	    {
		for (int x = 0; x < 10; x++) // Run until condition.
		{
		    if (x == 5 &&
			y == 5)
		    {
			goto Outer;
		    }
		}
		dummy++;
	    }
	Outer:
	    continue;
	}
	return dummy;
    }
}

Output

50
Note (please read)

Description. This code defines one custom method M. It contains three nested loops. The first loop iterates through numbers [0, 9], as do the two inner loops. However, in the third loop, a condition is checked that causes the loop to exit using the break keyword.

Break Statement

The code increments the dummy variable after each completion of the inner loop. If the inner loop is exited early, this variable shouldn't be incremented. The goto statement avoids this.

Result. The result of the code is that the value 50 is printed to the console. The int is incremented 10 x 5 times. If the goto was a break, the result would be 10 x 10 times.

Switch

Programming tip

The goto statement also can be used in a switch block. The switch allows control to be transferred to another case in this way. Please read the specific article for more detail.

Goto Switch Usage

Benchmark

Continuing on, we see how you can rewrite code that uses the break and continue keywords to use the goto and continue keywords. You may think the goto code is clearer. It uses one fewer variable.

Note: This benchmark is of limited utility. It does show how the JIT may be effected by the goto statement.

Code that uses break for loop [C#]

static int BreakMethod()
{
    int dummy = 0;
    for (int a = 0; a < 10; a++)
    {
	for (int y = 0; y < 10; y++) // Run until condition.
	{
	    bool ok = true;
	    for (int x = 0; x < 10; x++) // Run until condition.
	    {
		if (x == 5 &&
		    y == 5)
		{
		    ok = false;
		    break;
		}
	    }
	    if (!ok)
	    {
		break;
	    }
	    dummy++;
	}
	continue;
    }
    return dummy;
}

Code that uses goto on loop [C#]

static int GotoMethod()
{
    int dummy = 0;
    for (int a = 0; a < 10; a++)
    {
	for (int y = 0; y < 10; y++) // Run until condition.
	{
	    for (int x = 0; x < 10; x++) // Run until condition.
	    {
		if (x == 5 &&
		    y == 5)
		{
		    goto Outer;
		}
	    }
	    dummy++;
	}
    Outer:
	continue;
    }
    return dummy;
}
Break keyword

Break example. This code uses a flag variable named "ok". It initializes ok to true, but then sets ok to false and breaks when the exit condition is reached. This avoids incrementing the dummy variable. The result is 50.

Goto example. This code does the same functional thing as the other version that uses break. It detects the exit condition and uses goto to leave the inner loop. There is no flag variable used.

Benchmark description. The two methods above were placed in a benchmark framework. They were run in a loop for many iterations, and the function result was checked each time. They were run with the break first and the goto second, and the other way around.

Benchmark Programs

Results. The results were that goto performed worse when it was run first. The times for BreakMethod were 1036 ms, 1033 ms. GotoMethod times were 1029 ms, 1156 ms. Goto was slower in one of the two runs.

Performance results

break:   1033 ms   (goto tested first)
goto:    1156 ms

break:   1036 ms   (break tested first)
goto:    1029 ms

Interpretation

Just-in-time compiler (JIT)

The behavior observed here shows that goto is sometimes not optimized as well with the JIT compiler. The fact that it only is slower when called in the first loop might mean that the JIT does not compile it as aggressively. With these methods, break is faster because it is JIT optimized more reliably.

Summary

We saw that sometimes goto may look faster and convenient, but can actually confuse the runtime and result in poorer performance. In other words, goto is not only more complex for programmers, but is more difficult for the JIT compiler to optimize.

Loop Constructs
Dot Net Perls