HomeSearch

C# goto Examples: goto Label, goto case

Use the goto statement with labels and in switch cases. Goto transfers control to a new location.

Goto.

This keyword transfers control to a named label. It can be used to exit a deeply nested loop. Goto can help us understand branches and control flow.

The goto statement

is fairly powerful. We can use it in a loop or a switch. In practice, many developers never use goto (except maybe in a switch).Switch

An example.

This program that uses goto to exit a nested loop. We can use code that does the same thing without goto. But this would require a flag variable (usually a bool) to check.Bool

Note: Method syntax is another option to write code that has this functionality. With inlining, methods can be as fast as statements.

Label: With a label, we indicate where a goto-statement should transfer control.

Loops: TestGotoNestedLoops contains 3 nested loops. The first loop iterates through numbers [0, 9], as do the two inner loops.

For

But: In the third loop, a condition is checked that causes the loop to exit using the goto keyword.

C# program that uses goto, nested loops using System; class Program { static void Main() { Console.WriteLine("RESULT: " + TestGotoNestedLoops()); } static int TestGotoNestedLoops() { 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 RESULT: 50

Example 2.

We can rewrite code that uses the break and continue keywords to use the goto and continue keywords. The goto code uses one fewer variable.

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

Info: This code uses a flag variable named "ok". It sets "ok" to false and breaks when the exit condition is reached.

True, False

Next: Our goto example has the same effect. It detects the exit condition and uses goto to leave the inner loop. It has no flag variable.

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; }

Benchmark.

I placed the above 2 methods in a benchmark program. I ran them in a loop for many iterations. The function result was checked each time.Benchmark

And: I tested them with the break first and the goto second, and the other way around.

Results: Goto performed worse when it was run first. The version with break was more consistent in having good performance.

Performance results break: 1033 ms (goto tested first) goto: 1156 ms break: 1036 ms (break tested first) goto: 1029 ms

Switch.

Goto can be used in a switch block. Switch allows control to be transferred to another case in this way. This use of goto may be somewhat less confusing than others.

Syntax: There is a special syntax for this construct: it requires goto case or goto default. We examine this syntax form.

GetPrice: GetPrice() performs 3 logical steps, all defined in the switch-statement. We often find switches in single methods like this one.

Note: The method receives the ID of an item. If the ID is equal to 1000, the base price is increased by 10.

And: After this occurs, this ID is treated like a price of 100. It goes to that case.

C# program that uses goto statement in switch using System; class Program { static void Main() { Console.WriteLine(GetPrice(1000)); Console.WriteLine(GetPrice(-1)); Console.WriteLine(GetPrice(int.Parse("100"))); } static int GetPrice(int id) { // // Default price is 5. // int price = 5; // // When id is 1000, add 10 to price before multiplying. // switch (id) { case 1000: price += 10; // <-- Could get from another method goto case 100; case 100: return price * 10; default: return price; } // // 1. // First, if ID is 1000, add ten to default price. // // 2. // If ID is 1000 or 100, multiply price by 10 and return it. // // 3. // If ID is anything else, return price of 5. // } } Output 150 5 50

Benefits, switch.

Quality code is structured into discrete methods. We can call the same method with different values from a switch.

But: In certain cases we may benefit from goto in switch when trying to reduce method size. A benchmark shows this effect.

Method Size Test

Info: The greatest benefit of switches on ints or non-string constants here is that the low-level MSIL jump statement is used.

Int, uintSwitch EnumIL: switch

Error, goto.

When we have a goto, a matching label must be present. The label can be at the same scope level, or an enclosing scope (but not in a nested, enclosed scope).
C# program that shows goto error using System; class Program { static void Main() { goto BIRD; Console.WriteLine("BIRD"); } } Output Error CS0159 No such label 'BIRD' within the scope of the goto statement

Warning, goto.

If we have a label in a C# program that is not referenced, a warning will appear. This helps us keep our programs free of useless garbage statements.
C# program that shows goto warning using System; class Program { static void Main() { BIRD: Console.WriteLine("BIRD"); } } Output Warning CS0164 This label has not been referenced

Avoid goto.

In my experience, it is best not to use goto, even in switch statements. Using a method to encapsulate logic is better—it is more versatile, and can promote code sharing better.

Research.

Goto was part of the 1960s emergence of structural programming. In "Go To Statement Considered Harmful," Dijkstra observed how goto-statements make logic harder to follow.

And: New options, like methods, are clearer. With them, programs are less likely to deteriorate into unfathomable messes.

Quote: The go to statement as it stands is just too primitive, it is too much an invitation to make a mess of one's program (Edsger W. Dijkstra).

Quote: Formally, the goto is never necessary, and in practice it is almost always easy to write code without it.... It does seem that goto statements should be used rarely, if at all (The C Programming Language).

A summary.

Goto may look fast and convenient. But it can result in poorer performance. Thus goto is more complex for programmers, and harder for a JIT to optimize.
Home
Dot Net Perls
© 2007-2019 Sam Allen. All rights reserved. Written by Sam Allen, info@dotnetperls.com.