C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
It can be used to exit a deeply nested loop. As are many things, it is considered harmful. It can help us understand branches and control flow.
Example. To start, we examine a 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. Method syntax is another option.
Label: With a label, we indicate where a goto-statement should transfer control.
Based on: .NET 4.5 C# program that uses goto 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
In this example, method M contains three nested loops. The first loop iterates through numbers [0, 9], as do the two inner loops. But in the third loop, a condition is checked that causes the loop to exit using the break keyword.
The code increments the dummy variable after each completion of the inner loop. If the inner loop is exited early, this variable should be left alone. With the goto statement, it is not incremented.
Result: The value 50 is printed to the console. The int is incremented 10 x 5 times.
However: If the goto was a break, the result would be 10 x 10 times, or a total of 100.
Example 2. Continuing on, we show how to 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: Our benchmark is of limited utility. It does show how the JIT may be affected 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; }
This code uses a flag variable named "ok". It initializes the variable to true, but then sets it to false and breaks when the exit condition is reached. This avoids incrementing the dummy variable. The result is 50.
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.
Benchmark. I placed the above two methods in a benchmark program. I ran them in a loop for many iterations. The function result was checked each time. I tested them with the break first and the goto second, and the other way around.
So: The results were that goto performed worse when it was run first. Timings are shown next.
Performance results break: 1033 ms (goto tested first) goto: 1156 ms break: 1036 ms (break tested first) goto: 1029 ms
The behavior observed here shows that goto is sometimes not optimized as well with the JIT compiler. Goto is only slower when called in the first loop. This might mean that the JIT compiler does not work as well with it.
Therefore: With these methods, break is faster because it is more reliably JIT-optimized.
Switch. The goto statement also can be used in a switch block. The switch allows control to be transferred to another case in this way. Goto still transfers the flow of control, but causes somewhat less confusion in switch.
Tip: To look on the bright side, this can enhance performance and reduce code size in some cases.
Syntax: There is a special syntax for this construct: it requires goto case or goto default. We examine this syntax form.
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
In this example, we see a custom method called GetPrice defined. We often find switches in single methods like this one. GetPrice() performs three logical steps, all defined in the switch-statement.
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.
Next steps. For IDs of 1000 or 100, the value returned from the method is equal to the base price times 10. This occurs after IDs of 1000 were processed. For all other values, the price that is returned is the base price, which is 5.
Benefits, switch. Quality code is structured into discrete methods. We can simply 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.
Info: The greatest benefit of switches on ints or non-string constants here is that the low-level MSIL jump statement is used.
Research. Goto was part of the 1960s emergence of structural programming. In his famous text "Go To Statement Considered Harmful," Dijkstra observed how goto-statements make logic more complex, harder to follow.
And: New options, like methods, are clearer. With them, programs are less likely to deteriorate into unfathomable messes.
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: utexas.edu
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.
Summary. Goto may look fast and convenient. But it can confuse the runtime and result in poorer performance. Thus goto is not only more complex for programmers. It is more difficult for the JIT compiler to optimize.