Branching Statements: Conditional and Unconditional
AAHC

Click on A to make all fonts on the page smaller.

Click on A to make all fonts on the page larger.

Click on HC to toggle high contrast mode. When you move your mouse over some bold words in high contrast mode, related words are automatically highlighted. Text is shown in black and white.


In this lesson, we'll further explore the important concept of branching. We know that code is processed sequentially in a method, although depending on the code, the program may jump to another method in the same class, another method in another class, or even execute a C# or .Net-provided component or code. We've already created programs that use those kinds of branching, but let's take a more thorough look at this essential programming concept.

Unconditional Branching

C# provides the following Unconditional Branching techniques:

Some of these techniques and keywords you've seen and used before, such as methods, return, and break, but the rest are new. Let's take a look at each of these unconditional branching techniques a bit more. How? We'll create a new project, of course! However, some of the unconditional branching options available should only be used sparingly, and usually in only certain situations. We'll indicate those situations, and any issues to watch out for, as we work with each option. All program output will be sent to a ListBox. Unconditional branching statements are also frequently referred to as jump statements. We will not have a section about methods here; we'll devote an entire lesson to this important branching technique later.

Select File | New | Project, change the Name to Branching, and click OK. Find the entry for Form1.cs and change it to Branching.cs. Change the Form1 Form title bar's Text property in the Properties Window to Branching. Click .

Modify the form to look like this:

Change each control's Name property to match the Name Property column below, and Text property to match the Text Property column. Arrange the controls similar to the image. When you finish, click to save your changes.

ObjectName PropertyText Property
ListBoxoutputListBox 
ButtonexitButtonExit

Add an event handler for the exitButton control by double-clicking on the Exit Button to automatically generate the default event handler code. Studio generates an appropriate name for the event handler that consists of the name of the control, an underscore separator, and the event name.

Modify Branching.cs as shown below. The event handler code was added previously.

Branching.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Branching
{
    public partial class Branching : Form
    {
        public Branching()
        {
            InitializeComponent();
            
            // Unconditional branching methods.
            // return
            doReturnNoValue();
            doReturnWithValue();
            
            // break
            doBreak();
            
            // goto
            doGotoWithLabel();
            doGotoWithSwitch();
            
            // continue
            doContinue();
            
            // throw
            doThrow();
        }
        
        private void doReturnNoValue()
        {
            // Get method name.
            outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
        }
        
        private bool doReturnWithValue()
        {
            bool result = false;
            
            // Get method name.
            outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            
            return result;
        }
        
        private void doBreak()
        {
            // Get method name.
            outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
        }
        
        private void doGotoWithLabel()
        {
            // Get method name.
            outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
        }
        
        private void doGotoWithSwitch()
        {
            // Get method name.
            outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
        }
        
        private void doContinue()
        {
            // Get method name.
            outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
        }
        
        private void doThrow()
        {
            // Get method name.
            outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
        }
    
        private void exitButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    
    }
}

This first code is just a template to hold each section as we implement and discuss the various unconditional branching techniques. As you can see, we added calls to methods that will cover each of the techniques we will discuss. We did add one interesting line to each method: System.Reflection.MethodInfo.GetCurrentMethod().Name gets the name of the method we're in.

Click and . You should see the following output:

Now, let's add and discuss each branching section.

Modify Branching.cs as shown below to add code to the doReturnNoValue() method. (We'll understand if you cut and paste—just for this lesson!—the lengthy comments.) Note that only the doReturnNoValue() method is shown—no other code should change.

Branching.cs
.
.
.
private void doReturnNoValue()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // If your method has no return type, you normally would not use a return statement
    // as your program will exit normally. Good programming practice is to have a single exit
    // point from your code; however, if you need to immediately exit a method, especially
    // with deeply nested if statements, you might consider using a return.
    
    int testVariable = 3;
    int compareVariable = 4;
    
    if (compareVariable > testVariable)
    {
        if (testVariable < 10)
        {
            outputListBox.Items.Add("Return from if");
            return;
        }
        else
        {
            // Do some more checking.
            switch (testVariable)
            {
                case 1:
                    outputListBox.Items.Add("Return from switch case 1");
                    return;
                case 2:
                    outputListBox.Items.Add("Return from switch case 2");
                    return;
                default:
                    testVariable++;
                    break;
            }
        }
    }
    outputListBox.Items.Add("Normal method termination");
}
.
.
.

Click and . You should see the following output:

Let's discuss how this code works.

OBSERVE: Branching.cs
.
.
.
private void doReturnNoValue()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // If your method has no return type... 
    
    int testVariable = 3;
    int compareVariable = 4;
    
    if (compareVariable > testVariable)
    {
        if (testVariable < 10)
        {
            outputListBox.Items.Add("Return from if");
            return;
        }
        else
        {
            // Do some more checking.
            switch (testVariable)
            {
                case 1:
                    outputListBox.Items.Add("Return from switch case 1");
                    return;
                case 2:
                    outputListBox.Items.Add("Return from switch case 2");
                    return;
                default:
                    testVariable++;
                    break;
            }
        }
    }
    outputListBox.Items.Add("Normal method termination");
}
.
.
.

This method demonstrates how to use the return keyword from anywhere within a method, without returning a value. The doReturnNoValue() specifies a return type of void, so no value may be returned. This code illustrates a possible reason to use a return statement with deeply nested if statements, although the example isn't that deeply nested. Notice that within the switch's case statements, the return statement will immediately exit the method, so you do not need a break statement.

Modify Branching.cs as shown below to add the code to the doReturnWithValue() method. Note that only this method is shown; no other code should change.

Branching.cs
.
.
.
private bool doReturnWithValue()
{
    bool result = false;
    
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // A return statement is required when a method has a return type (bool in this example). You
    // can have multiple return statements, with different values, although good programming practice
    // is to have a single exit point from your code.
    
    int myAge = 18;
    
    if (myAge > 21)
        result = true;
    else if (myAge >= 18)
    {
        // Do some more checking.
        switch (myAge)
        {
            case 18:
                outputListBox.Items.Add("Return false from switch case 18");
                return false;
            case 19:
                outputListBox.Items.Add("Return true from switch case 19");
                return true;
            case 20:
                outputListBox.Items.Add("Return false from switch case 20");
                return false;
            default:
                myAge++;
                break;
        }
    }

    outputListBox.Items.Add("Normal method termination, return value is " + result);
    return result;
}
.
.
.

Click and . You should see the following output:

Let's discuss how this code works.

OBSERVE: Branching.cs
.
.
.
private bool doReturnWithValue()
{
    bool result = false;
    
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // A return statement is required when...
    
    int myAge = 18;
    
    if (myAge > 21)
        result = true;
    else if (myAge >= 18)
    {
        // Do some more checking.
        switch (myAge)
        {
            case 18:
                outputListBox.Items.Add("Return false from switch case 18");
                return false;
            case 19:
                outputListBox.Items.Add("Return true from switch case 19");
                return true;
            case 20:
                outputListBox.Items.Add("Return false from switch case 20");
                return false;
            default:
                myAge++;
                break;
        }
    }
    
    outputListBox.Items.Add("Normal method termination, return value is " + result);
    return result;
}
.
.
.

This method demonstrates how to use the return keyword from anywhere in a method, even when returning a value (in this case, we use the literal true or false, or the result variable, which is set to true or false depending on the value of myAge). The doReturnWithValue() specifies a return type of bool, so all returns must return a bool regardless of where the return is used.

Modify Branching.cs as shown below to add the code to the doBreak() method. Only this method is shown; no other code should change.

Branching.cs
.
.
.
private void doBreak()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // A break statement exits an enclosing loop, such as a while, do, for, or foreach, or a switch statement.
    // It must be used with one of these C# constructs. Other than with switch statements, excessive use of
    // break statements within loops can lead to confusion.
    
    int partialCount = 0;
    
    // while (or do) - watch out for infinite loops.
    while (true)
    {
        if (partialCount > 5)
            break;
        partialCount++;
    }
    
    // for (or foreach)
    for (int i = 0; i < 10; i++)
    {
        if (i < 5)
            break;
        partialCount++;
    }
    
    // switch
    switch (partialCount)
    {
        case 5:
            partialCount *= 5;
            break;
        case 10:
            partialCount *= 10;
            break;
        default:
            partialCount++;
            break;
    }
    
    outputListBox.Items.Add("Partial count: " + partialCount);
}
.
.
.

Click and . You should see the following output:

Let's discuss how this code works.

OBSERVE: Branching.cs
.
.
.   
private void doBreak()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // A break statement exits an enclosing loop...
    
    int partialCount = 0;
    
    // while (or do) - watch out for infinite loops.
    while (true)
    {
        if (partialCount > 5)
            break;
        partialCount++;
    }
    
    // for (or foreach)
    for (int i = 0; i < 10; i++)
    {
        if (i < 5)
            break;
        partialCount++;
    }
    
    // switch
    switch (partialCount)
    {
        case 5:
            partialCount *= 5;
            break;
        case 10:
            partialCount *= 10;
            break;
        default:
            partialCount++;
            break;
    }
    
    outputListBox.Items.Add("Partial count: " + partialCount);
}
.
.
.

This method demonstrates the multiple ways you can use the break keyword, exiting looping structures or the switch structure. The break immediately exits the enclosing structure.

Modify Branching.cs as shown below to add the code to the doGotoWithLabel() method. Note that only this method is shown; no other code should change.

Branching.cs
.
.
.
private void doGotoWithLabel()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // A goto statement transfers program control directly to another section of the code identified
    // by a label. Goto statements can transfer control out of a block, such as below where the code
    // transfers control out of an if statement. You can not transfer control into a block. Remember, 
    // a block is indicated by curly braces. Even though in this example the labeling is pretty clear,
    // other mechanisms exist that would not require the use of goto and labels. Also, labels may
    // easily be far removed from any goto statements, thus obscuring the flow and logic of the code,
    // so good programming practice discourages the use of goto statements.
    
    int anyNumber = 3;
    
    if (anyNumber % 2 == 0)
        goto Even;
    else
        goto Odd;
    
    Odd:
        outputListBox.Items.Add("The number is odd");
        goto Finish;
    Even:
        outputListBox.Items.Add("The number is even");
    
    Finish:
        outputListBox.Items.Add("Conclusion");
}
.
.
.

Click and . You should see the following output:

Let's discuss how this code works.

OBSERVE: Branching.cs
.
.
.
private void doGotoWithLabel()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // A goto statement ...
    
    int anyNumber = 3;
    
    if (anyNumber % 2 == 0)
        goto Even;
    else
        goto Odd;
    
    Odd:
        outputListBox.Items.Add("The number is odd");
        goto Finish;
    Even:
        outputListBox.Items.Add("The number is even");
    
    Finish:
        outputListBox.Items.Add("Conclusion");
}
.
.
.

The doGotoWithLabel method demonstrates the use of the goto statement with labels: Odd, Even, and Finish. The goto statement immediately transfers control to the specified labels.

Modify Branching.cs as shown below to add the code to the doGotoWithSwitch() method. Note that only this method is shown. No other code was changed. Click the Save button to save your changes.

Branching.cs
.
.
.
private void doGotoWithSwitch()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // Same notes as in doGotoWithLabel about goto statements apply.
    
    string dayOfWeek = "Saturday";
    bool isWeekend = true;
    
    switch (dayOfWeek)
    {
        case "Saturday":
            isWeekend = true;
            break;
        case "Sunday":
            goto case "Saturday";
        case "Monday":
            isWeekend = false;
            break;
        case "Tuesday":
            goto case "Monday";
        case "Wednesday":
            goto case "Monday";
        case "Thursday":
            goto case "Monday";
        case "Friday":
            goto case "Monday";
        default:
            outputListBox.Items.Add(dayOfWeek + " is not a valid week day");
            break;
    }
    
    outputListBox.Items.Add(dayOfWeek + (isWeekend?" is ":" is not") + "a week day");
}
.
.
.

Click and . You should see the following output:

Let's discuss how this code works.

OBSERVE: Branching.cs
.
.
.
private void doGotoWithSwitch()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // Same notes as in doGotoWithLabel about goto statements apply.
    
    string dayOfWeek = "Saturday";
    bool isWeekend = false;
    
    switch (dayOfWeek)
    {
        case "Saturday":
            isWeekend = true;
            break;
        case "Sunday":
            goto case "Saturday";
        case "Monday":
            isWeekend = false;
            break;
        case "Tuesday":
            goto case "Monday";
        case "Wednesday":
            goto case "Monday";
        case "Thursday":
            goto case "Monday";
        case "Friday":
            goto case "Monday";
        default:
            outputListBox.Items.Add(dayOfWeek + " is not a valid week day");
            break;
    }
    
    outputListBox.Items.Add(dayOfWeek + (isWeekend?" is ":" is not") + "a week day");
}
.
.
.

The doGotoWithSwitch method demonstrates the use of the goto statement with case statements within a switch statement. The goto statement immediately transfers control to the specified case statement.

Tip You might be curious why the parenthesis surround the ternary ? : expression. The reason is that addition has a higher precedence than the ternary/conditional operator, so the code attempts to perform an addition of a string (dayOfWeek)and bool (isWeekend), which is invalid. Wrapping the ternary expression with parenthesis changes the precedence, allowing the ternary evaluation to take place, resulting in a string result.

Modify Branching.cs as shown below to add the code to the doContinue() method. Note that only this method is shown. No other code was changed. Click the Save button to save your changes.

Branching.cs
.
.
.
private void doContinue()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // The continue statement is used to skip to the next iteration of any enclosing iterating statements,
    // such as while, do, for, or foreach. Execution is immediately transferred to the beginning of the body
    // of that iteration statement. Good programming practices recommend using the continue sparingly to avoid
    // obscuring the logic and flow of the source code.
    
    int startNumber = 3;
    int endNumber = 100;
    int count = 0;
    
    for (int i = startNumber; i <= endNumber; i++)
    {
        // Only cound odd numbers
        if (i % 2 == 0)
            continue;
        count++;
    }
    
    outputListBox.Items.Add("Odd number count: " + count);
}
.
.
.

Click and . You should see the following output:

Let's discuss how this code works.

OBSERVE: Branching.cs
.
.
.
private void doContinue()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // The continue statement is used to skip to the next iteration of any enclosing iterating statements,
    // such as while, do, for, or foreach. Execution is immediately transferred to the beginning of the body
    // of that iteration statement. Good programming practices recommend using the continue sparingly to avoid
    // obscuring the logic and flow of the source code.
    
    int startNumber = 3;
    int endNumber = 100;
    int count = 0;
    
    for (int i = startNumber; i <= endNumber; i++)
    {
        // Only cound odd numbers
        if (i % 2 == 0)
            continue;
        count++;
    }
    
    outputListBox.Items.Add("Odd number count: " + count);
}
.
.
.

The doContinue method demonstrates the use of the continue statement, which forces a skip to the next iteration of the enclosing iterating statement, in this case, a for loop, skipping the count++ statement.

Note The continue statement is used to skip to the next iteration of any enclosing iterating statements, such as while, do, for, or foreach. Execution is immediately transferred to the beginning of the body of that iteration statement. Good programming practices recommend using the continue sparingly to avoid obscuring the logic and flow of the source code.

Modify Branching.cs as shown below to add the code to the doThrow() method. Note that only this method is shown. No other code was changed. Click the Save button to save your changes.

Branching.cs
.
.
.
private void doThrow()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // The throw statement is used to signal that an anomalous situation, also known as an exception,
    // has occurred. Exceptions are handled using try..catch blocks. If an exception occurs in a program,
    // the system looks for a try..catch block that will handle the exception. These exceptions are 
    // raised by C# even if you do not throw an exception. Throwing an exception is usually done
    // by the user with custom exceptions to use the try..catch block to handle unusual circumstances
    // that might occur. This code demonstrates how to throw a standard exception, divide
    // by zero, but even if you had not thrown the exception, it would have been raised when
    // the actual divide by zero was attempted. Without a try..catch block, the system will 
    // stop on the exception.
    
    int numerator = 10;
    int denominator = 0;
    int result = 0;
    
    if (denominator == 0)
        throw new DivideByZeroException();
    else
        result = numerator / denominator;
}
.
.
.

Click and . You will see the following exception. Click the to stop the program so we can correct the error after we discuss how the code works.

OBSERVE: Branching.cs
.
.
.
private void doThrow()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // The throw statement...
    
    int numerator = 10;
    int denominator = 0;
    int result = 0;
            
    if (denominator == 0)
        throw new DivideByZeroException();
    else
        result = numerator / denominator;
}
.
.
.

The doThrow method demonstrates how to throw an exception. Exceptions are situations that are unexpected, but would cause a serious problem if the exception is not correctly dealt with. Examples of exceptions include a database connection becomes invalid, access to the network is disabled, or an attempt to divide by 0, as in our example. Unhandled exceptions will cause the program to either become unstable, unusable, or to stop functioning. In doThrow, we detect if denominator is 0, and if so, we throw a DivideByZeroException, creating an instance of that exception during the throw. This situation is a bit contrived, as we have already detected that the denominator is 0, so we have other possible ways of dealing with it, such as telling the user that the denominator must not be 0.

Since this code as written will raise an exception and freeze the code, let's add a try..catch block to allow the program to continue to function.

Modify Branching.cs as shown below to add the code to the doContinue() method to handle the DivideByZeroException. Note that only this method is shown. No other code was changed. Click the Save button to save your changes.

Branching.cs
.
.
.
private void doThrow()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // The throw statement...
    
    int numerator = 10;
    int denominator = 0;
    int result = 0;
    
    try
    {
        if (denominator == 0)
            throw new DivideByZeroException();
        else
            result = numerator / denominator;
    }
    catch (Exception ex)
    {
        outputListBox.Items.Add(ex.Message);
    }
}
.
.
.

Click and . You should see the following output:

Let's discuss how this code works.

OBSERVE: Branching.cs
.
.
.
private void doThrow()
{
    // Get method name.
    outputListBox.Items.Add("=> Method: " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
    
    // The throw statement...
    
    int numerator = 10;
    int denominator = 0;
    int result = 0;
    
    try
    {
        if (denominator == 0)
            throw new DivideByZeroException();
        else
            result = numerator / denominator;
    }
    catch (Exception ex)
    {
        outputListBox.Items.Add("You cannot divide by 0");
    }
}
.
.
.

Now, when you run the program, the doThrow method will still throw the DivideByZeroException exception, but now the try..catch block will "catch" the error. We'll cover try..catch blocks and exceptions more later.

Note As mentioned above, we actually do not need to throw the exception, as the attempt to divide by zero would have raised the same exception. Later, we'll introduce custom exceptions, so knowing how to throw an exception now will prepare you for that lesson.
Conditional Branching

Let's take a look at the C# list of Conditional Branching techniques:

Sprinkled throughout our unconditional branching, you can find examples of all of these conditional branching techniques, so we do not need to provide more sample code for you to enter. We should reiterate a couple of points:

Before you move on to the next lesson, do your homework! Right-click in the window where this lesson text appears and select Back. Then select Quiz for this lesson in the syllabus and answer the quiz questions. When you finish the quiz questions, click HAND IT IN at the bottom of that window. Then do the same with the Project(s) for the lesson. Your instructor will grade your quiz(zes) and project(s) and provide guidance if needed.