All the statements in your program execute in order. Unfortunately, that’s not very useful, unless you want your program to do exactly the same thing every time you run it. In fact, often you won’t want to execute all the code, but rather you’ll want the program to do one thing if a variable has a certain value, and something different if the variable has another value. That means you need to be able to cause your program to pick and choose which statements to execute based on conditions that change as the program runs. This process is called branching, and there are two ways to accomplish it: unconditionally or conditionally.
As the name implies, unconditional branching happens every time the branch point is reached. An unconditional branch happens, for example, whenever the compiler encounters a new method call. The compiler stops execution in the current method and branches to the newly called method. When the newly called method returns (completes its execution), execution picks up in the original method on the line just below the branch point (the line where the new method was called).
Conditional branching is more complicated. Methods can branch based
on the evaluation of certain conditions that occur at runtime. For
instance, you might create a branch that will calculate an employee’s
federal withholding tax only when their earnings are greater than the
minimum taxable by law. C# provides a number of statements that support
conditional branching, such as if
,
else
, and switch
. The use of these statements is discussed
later in this chapter.
A second way that methods break out of their mindless step-by-step
processing of instructions is by looping. A loop causes the method to
repeat a set of steps until some condition is met (“Keep asking for input
until the user tells you to stop or until you receive ten values”). C#
provides many statements for looping, including for
, while
,
and do...while
, which are also
discussed in this chapter.
The most simple example of an unconditional branch is a method call. When a method call is reached, there is no test made to evaluate the state of the object; the program execution branches immediately (and unconditionally) to the start of the new method.
You call a method by writing its name; for example:
UpdateSalary(); // invokes the method UpdateSalary
As I explained earlier in the chapter, when the compiler encounters a method call, it stops execution of the current method and branches to the new method. When that new method completes its execution, the compiler picks up where it left off in the original method. This process is illustrated schematically in Figure 5-1.
As Figure 5-1
suggests, it is actually quite common for there to be unconditional
branching several methods deep. In Figure 5-1, execution begins
in a method called Main( )
.
Statement1 and Statement2 execute; then the compiler sees a call to
Method1( )
. Program execution
branches unconditionally to the first line of Method1( )
, where its first three statements
are executed. At the call to Method1A( )
, execution again branches, this time to the start of
Method1A( )
.
The four statements in Method1A( )
are executed, and Method1A( )
returns. Execution resumes on the first statement after the
method call in Method1( )
(Statement4). Execution continues until Method1( )
ends, at which time execution
resumes back in Main( )
at
Statement3. At the call to Method2( )
, execution again branches; all the statements in Method2( )
execute, and then Main( )
resumes at Statement4. When Main( )
ends, the program itself ends.
You can see the effect of method calls in Example 5-1. Execution begins
in Main( )
, but branches to a method
named SomeMethod( )
. The WriteLine( )
statements in each method assist
you in seeing where you are in the code as the program executes.
Example 5-1. Branching to a method
using System; class Functions { static void Main( ) { Console.WriteLine( "In Main! Calling SomeMethod( )..." ); SomeMethod( ); Console.WriteLine( "Back in Main( )." ); } static void SomeMethod( ) { Console.WriteLine( "Greetings from SomeMethod!" ); } }
The output looks like this:
In Main! Calling SomeMethod( )... Greetings from SomeMethod! Back in Main( ).
Program flow begins in Main( )
and proceeds until SomeMethod( )
is
invoked. (Invoking a method is sometimes referred to as
calling the method.) At that point, program flow branches to the
method. When the method completes, program flow resumes at the next line
after the call to that method.
You can instead create an unconditional branch by using one of
the unconditional branch keywords: goto
, break
, continue
, return
, or throw
. The first four of these are discussed
later in this chapter, while the final statement, throw
, is discussed in Chapter 16.
Methods and their parameters and return values are discussed in detail in Chapter 8.