This is the second part of a two-part series on C# Jump Statements. In the first part, We delved into break
and continue
statements and how they works in nested loop. Check it out in case you missed it.
In this guide, we will focus on another important jump statement: goto
statement. We will talk about the scope of usages and also pointed out the side effect of goto
. Then we will mention other jump statements.
As the last guide of C# flow control, we will summarize the relation between iterative, conditional and jump statements.
As a tutorial for beginners, I try my best to use vivid visualizations and examples to help you understand.
goto
is a powerful jump statement. It can jump to anywhere in the same action scope. You can use goto
to customize your logic flow, even use it to simulate recursion, iteration, and selection.
There are two ways to use goto
in C#:
goto
in switch
: it is the only way a non-empty case falls through to another case in C# switch.goto
with label: First, we label a statement
by label_name: statement;
, then we can goto
this statement via label_name
. Notice label should be defined in the same action scope.goto
in switch
Let's practice goto
in switch
with the following hard-working programmer example:
1string state = "hungry";
2switch (state)
3{
4 case "normal":
5 Console.WriteLine("coding..");
6 goto default; // jump to default branch
7 case "hungry":
8 Console.WriteLine("eat some stuff");
9 goto case "normal"; // jump to "normal" branch
10 case "illness":
11 Console.WriteLine("see a doctor");
12 break;
13 default:
14 Console.WriteLine("go to sleep");
15 break;
16}
If state
is "hungry", first process "hungry" case logic, then jump to "normal" branch, finally fall through to default
.
1eat some stuff
2coding..
3go to sleep
goto
with LabelFor goto
with label, the most appropriate usages are jumping in multiple nested loops or conditions.
We have learned break
can only take effect on the current loop in nested loops. A straightforward idea is using a flag to mark the state, and process it in outer loops.
Here is a version of nested loops with flag:
1int[,,] arr = new int[2, 3, 2] {
2 { { 1, 2 }, { 3, 4 }, { 5, 6 } },
3 { { 7, 8 }, { 9, 10 }, { 11, 12 } } };
4
5bool flag = false;
6for (int i = 0; i < arr.GetLength(0); ++i)
7{
8 for (int j = 0; j < arr.GetLength(1); ++j)
9 {
10 for (int k = 0; k < arr.GetLength(2); ++k)
11 {
12 if (arr[i, j, k] == 7)
13 {
14 flag = true;
15 break;
16 }
17 Console.WriteLine("current element is {0}", arr[i, j, k]);
18 }
19 if (flag)
20 break;
21 }
22 if (flag)
23 break;
24}
25Console.WriteLine("break multiple loops when value is 7");
This is the version with goto
:
1for (int i = 0; i < arr.GetLength(0); ++i)
2{
3 for (int j = 0; j < arr.GetLength(1); ++j)
4 {
5 for (int k = 0; k < arr.GetLength(2); ++k)
6 {
7 if (arr[i, j, k] == 7)
8 goto Finish;
9 Console.WriteLine("current element is {0}", arr[i, j, k]);
10 }
11 }
12}
13Finish: Console.WriteLine("break multiple loops when value is 7");
Pretty concise and elegant, right?
Except for the above two main usages, here are some other usages.
We can regard goto
as the way to customize our control flow, such as simulating recursion, iteration, and selection.
We use do-while as an example to show how to use goto
to simulate:
1// do-while template
2do
3{
4 code_block;
5} while (condition);
6
7// rewritten by goto
8Loop: code_block;
9if (condition)
10 goto Loop;
Here is the for-else statement in python. If not break
from the loop, it will execute the else
part.
1for x in range(5):
2 if x == 3:
3 print("find 3 in loop")
4 break
5else:
6 print("not find 3 in loop") # reach there when not break
C# don't support for else
, but we can achieve this by goto
easily.
1for (int i = 0; i < 5; ++i)
2{
3 if (i == 3)
4 {
5 Console.WriteLine("find 3 in loop");
6 goto Finish;
7 }
8}
9Console.WriteLine("not find 3 in loop");
10Finish: Console.WriteLine("end of loop");
But these usages are not recommended. We will discuss the side-effect of goto
later.
Once goto
is invented, arguments never stop. I refer to the famous opinions from wiki goto:
Probably the most famous criticism of GOTO is a 1968 letter by Edsger Dijkstra called Go To Statement Considered Harmful. In that letter, Dijkstra argued that unrestricted GOTO statements should be abolished from higher-level languages because they complicated the task of analyzing and verifying the correctness of programs (particularly those involving loops). An alternative viewpoint is presented in Donald Knuth's Structured Programming with go to Statements which analyzes many common programming tasks and finds that in some of them GOTO is the optimal language construct to use.
Here is a negative example of goto
, with spaghetti code twisted together:
1// negative example of goto, tangled code
2int x = 0;
3Label1: x += 1;
4if (x % 2 == 0)
5 goto Label1;
6if (x % 3 == 0)
7 goto Label2;
8Console.WriteLine(x);
9Label2: if (x < 10)
10 goto Label1;
The readability is awful. It is weakly structured and hard to debug or maintain.
My suggestion is:
In modern language, there are many alternatives for goto, such as context manager, design pattern, and other control flow methods. Except for usages in switch and nested loops, we should avoid using goto as much as possible.
There are other jump statements, but they are applied to specific situations.
return
statement terminates the execution of the method in which it appears and returns control to the calling method. throw
an exception when an anomaly occurs and abandon the rest logic.We mainly focus on the general jump statements and are not going to expand them here. You can refer to the official documents if you are interested.
We have learned all the basic control flow statements. At the end of this series, let's summarize the relation between iterative, conditional and jump statements.
I draw a relation diagram to help you understand:
They depend on each other and enhance each other.
They are inseparable. They are indispensable.
Together, they form complex program logic.
In this guide, we have learned another jump statement: goto
statement. We analyzed the syntax and flowchart of goto
and practiced with examples. We talked about the scope of usage and also pointed out the side effect of goto
. Besides, we mentioned other jump statements. In the end, we summarized the relation between iterative, conditional and jump statements.
As this is the end, I have drawn a mind map to help you organize and review the knowledge in this series.
This guide is one of a series of C# Flow Control guides:
Hope you enjoyed it. If you have any questions, you’re welcome to contact me at [email protected].