In this article, the latest of our C# in Simple Terms series, we're going to discuss how to control the flow of execution in a C# program. This means we will answer the question, "how does the code know what to do next?"

Our C# programs know what lines of code to execute next through the use of two sets of keywords: the selection statement keywords, and the loop keywords.

Looking down the middle of a long spiral staircase with a red barrier, descending into darkness, where the bottom is not visible.
I think someone forgot the end condition. Photo by Tine Ivanič / Unsplash

The Sample Project

exceptionnotfound/CSharpInSimpleTerms
Contribute to exceptionnotfound/CSharpInSimpleTerms development by creating an account on GitHub.
Project for this post: 5BasicStatementsAndLoops

Code Blocks

In C#, a code block is a group of lines of code between curly braces {}.

{
    //Everything between { and } is part of this code block.
}

Both selection statement keywords and loops work with code blocks, though in different ways.

Selection Statement Keywords

These keywords cause "decision points" in C# programs, where the program may or may not execute a code block based on whether a condition or set of conditions is true.

In C#, this set of keywords consists of if, else, switch, case, and break. Let's take a closer look at each of these keywords.

If, Else, If Else

The most basic of the selection statement keywords are if and else. We use these keywords to evaluate boolean expressions and direct the program to execute specified lines of code if certain expressions are true.

if (expression) //If this expression evaluates to true...
{
    //...Execute this
}
else
{
    //Otherwise, execute this
}

We can also use an else if clause to add more conditions to our evaluation.

decimal money;
decimal orderTotal;

if (money > orderTotal)
{
    Console.WriteLine("Thanks for your purchase!");
}
else if (money == orderTotal)
{
    Console.WriteLine("Wow! Thanks for having exact change!");
}
else
{
    Console.WriteLine("Sorry, you don't have enough money.");
}

An if statement can be implemented alone. if else statements and else statements must follow an if statement. We can have as many if else statements as we like in a given set.

We can also nest if and else statements to form more complex decisions:

if(expression1)
{
    if(expression2)
    {
        if(expression3) { /*...*/ }
        else if(expression4) { /*...*/ }
        else ( /*...*/ }
    }
    else 
    {
        if(expression5) { /*...*/ }
        /*...*/ //These lines of code will be executed 
                //whenever the containing else statement is executed.
    }
}

Switch, Case, Break

Sometimes we want to evaluate a given object against a large set of possible values. For these situations, we use the keyword switch and its related keywords case and break.

A switch statement is used when a single object needs to be evaluated against a large number of potential values. Each of these possible values is identified by using a case statement. The case statement can consist of multiple lines of code, and ends when the system encounters the break keyword.

switch(variable)
{
    case value1:
        executeThis();
        executeThat();
        break;
        
    case value2:
        executeThisOtherThing();
        break;
        
    default:
        break;
}

For example, let's imagine we have a company that is sponsoring us for a tournament of some kind. We want to display the company a message, but we need it to be a different message for each level of sponsorship that we offer. We might implement a switch statement to output the correct message for each sponsorship level:

var sponsorLevel = 2;

switch (sponsorLevel)
{
    case 1: //Gold
        Console.WriteLine("Thanks for being a gold sponsor!");
        break;

    case 2: //Silver
        Console.WriteLine("Thanks for being a silver sponsor!");
        break;

    case 3: //Bronze Level 2
    case 4: //Bronze Level 1
        Console.WriteLine("Thank you for being a bronze sponsor!");
        break;

    default: //All others
        Console.WriteLine("Thank you for sponsoring us!");
        Console.WriteLine("Would you like to upgrade to a bronze sponsorship?");
        break;
}

Note that we can have multiple case statements use the same block of code by "stacking" them, like case 3 and case 4 in the example above.

Switch Expression

When we need a switch statement to only produce a concrete value, we can use a switch expression.

For example, let's say we have a set of cards. Each card has a resource type, and a color. The cards with a given resource type always have the same color. If the color and resource type are enumerations (which we will discuss in a later post), we can use a switch expression to give us the color if we have the resource type.

public enum CardColor
{
    Brown,
    Grey,
    Blue,
    Green,
    Yellow,
    Red,
    Purple
}

public enum CardType
{
    NaturalResource,
    ManufacturedResource,
    Cultural,
    Science,
    Economic,
    Military,
    Guilds
}

public static void Main()
{
    var cardType = GetCardType(cardID); //Method not defined here
    
    var cardColor = cardType switch //Switch expression
    {
        CardType.NaturalResource => CardColor.Brown,
        CardType.ManufacturedResource => CardColor.Grey,
        CardType.Cultural => CardColor.Blue,
        CardType.Science => CardColor.Green,
        CardType.Economic => CardColor.Yellow,
        CardType.Military => CardColor.Red,
        CardType.Guilds => CardColor.Purple
    };
}
Extra special bonus points to whoever knows what this is from.

In short, "decision point" statements like if, else, and switch help our applications perform different code depending on specified conditions.

Loops

In C#, loops are code blocks that are executed multiple times. The exact number of times they are executed can differ, or be dependent on a variable, or on a collection of objects.

There are four ways to implement a loop in C#, and they each have a distinct use.

For Loop

A for loop is a loop that executes once for each value in a given range. The loop must define a variable (commonly named i or j, termed the initializer); a condition where the loop will execute again so long as the condition is true; and an iterator which defines by how much the initializer will change after every loop.

A common kind of for loop uses integers and a simple increment.

for(int i = 0; //Initializer
    i < 10; //Condition
    i++) //Iterator
{
    //This code will execute ten times, 
    //one each for i = 0, i = 1, up to and including i = 9.
}

We can also use increments of values other than 1:

for (int i = 0; i < 10; i += 2) //+= is Increment Assignment Operator
{
    //This code will execute five times.
    //i = 0, i = 2, i = 4, i = 6, and i = 8
}

for loops are particularly useful if we know the range of values that we want to loop against in advance.

Foreach Loop

When dealing with collections of objects (such as an array or a List<T>; both of which will be discussed later in this series), we can use a foreach loop to iterate over every object in the collection. In this case, the iterator object is of the same type as objects in said collection.

var items = new int[] {4, 5, 6, 7, 8};
foreach(int item in items)
{
    Console.WriteLine(item);
}

//Example class
public class Drawing
{
    public string Name { get; set; }
}

//Make a collection of Drawings
List<Drawing> drawings = new List<Drawing>() 
{
    new Drawing()
    {
        Name = "Test Drawing 1"
    },
    new Drawing()
    {
        Name = "Test Drawing 2"
    }
};

//Iterate over each drawing in the collection
foreach (Drawing iterator in drawings) //iterator is of type Drawing
{
    Console.WriteLine(iterator.Name);
}

Using a foreach loop to iterate over a collection is the most common scenario for this kind of loop.

While Loop

A while loop evaluates a condition, and so long as that condition is true, the loop will keep executing.

int myVal = 0;
while(myVal < 1000) //This loop will execute 1000 times...
{
    DoSomething();
    DoSomethingElse();
    myVal = myVal + 1; //...because each time through the loop, we 
                       //increase the value of myVal by 1
}

We must be careful when writing while loops; it is easy to accidentally create a loop that will never reach the end condition.

int myVal = 5;
while(myVal < 1000)
{
    DoSomething();
    DoSomethingElse();
    //We didn't increment myVal, so this loop will never stop executing!
}

Because a while loop evaluates the condition before entering the loop, if that condition is false before the loop starts, the loop will not be executed.

Do While Loop

By contrast, a do while loop will always execute at least once, because the condition is evaluated at the end of the loop.

int myVal = 1;
do
{
    DoSomething();
    DoSomethingElse();
    myVal++;
} while (myVal < 1000);

If you must guarantee that the code in a loop run at least one time, use a do while loop.

Breaking the Loop

In many situations, we may want to stop executing the loop before the loop reaches its end condition. There are several keywords we can use for these situations.

Break

The break keyword ends execution of the loop. No further iterations of the loop will execute.

for(int i = 0; i < 10; i++)
{
    if(i == 7)
    {
        break; //Will exit the for loop
    }
}

You might have noticed that this keyword was also used in the switch statement examples above, and its function was similar there.

Continue

The continue keyword ends execution of the current iteration of the loop, but will restart the loop at the next iteration.

int myVal = 5;
while (myVal < 10)
{
    if (myVal == 7)
    {
        myVal++;
        continue; //If i == 7, processing stops here and resumes
                  //at the top of the loop with the next value 8.
                  //Console.WriteLine is never called in that case.
    }
    //The below output will not happen when myVal = 7
    Console.WriteLine("The current value of myVal is " + myVal.ToString());
    myVal++;
}

Return

The return keyword, similarly to how it works in methods, will return a value to the calling code. The loop will therefore stop executing.

var emails = GetEmails(); //Method not defined here

foreach(var email in emails)
{
    if(email.Sender == "[email protected]")
    {
        return email; //Loop stops executing
    }
}

New Keywords

  • if - Specifies a block of code that will executed if a particular condition is true.
  • else if - Specifies a block of code that will executed if a particular condition is true. Must be used in tandem with an if.
  • else - Specifies a block of code that will be executed if non of the previous if statements were executed. Must be used with an if.
  • for - Specifies a loop that will execute a defined number of times. Must have an initializer, a condition, and an increment.
  • foreach - Specifies a loop that will execute once for each item in a collection, unless the loop is broken.
  • while - Specifies a loop that will execute so long as a given condition is true.
  • do while - Specifies a loop that will execute at least once, and then will continue executing as long as the condition is true.
  • break - Stops execution of a loop OR marks the end point of a case in a switch statement.
  • continue - Stops the current iteration of a loop, and resumes execution at the next iteration.
  • return - Stops execution of a loop and returns a value to the calling code.

Summary

In C#, we control the flow of execution in our programs by using "decision point" statements such as if, else, and switch and by creating one of the four kinds of loops: for, foreach, while, and do while. We can also stop or modify execution of those loops using the break, continue, and return keywords.

Woo hoo! We're getting our foundational knowledge down! In the next part of this series, we begin combining our knowledge of control flow and operators to build the next step in our C# program: methods!

C# in Simple Terms - Methods, Parameters, and Arguments
Let’s make some methods, pass some parameters, and accept some arguments!

Got questions about this post? I'm happy to hear them! Ask questions in the comments below and let's see if we can get you some answers!

Happy Coding!