Basic constructs

Armed with all the knowledge we have gained so far, let us take a quick look at several C# language constructs that can help us direct the execution flow of our program.

If/else statement

The most commonly used is probably the “if/else” statement. It directs the execution flow based on an evaluation of a logical condition. Let us take a look at the following bartender example:

int customerAge = 18;

if (customerAge < 18)
    Console.WriteLine("Can't serve drinks!");
else
    Console.WriteLine("What can I get you?");

Console.ReadLine();

Here if the customerAge is lower than 18, the code below the “if” statement will be executed. In any other case (that is if customerAge equals or is greater than 18), the code below the else statement will be executed.

Since customerAge is set to 18 in our example, the application will yield the following output:

What can I get you?

If there is only a single statement under the “if” or “else” statements, it can be written exactly as in the example above – just directly below the “if” or “else” statements. Another option is to use the curly braces:

if (true)
{
    Console.WriteLine("Optional curly braces");
}

If there are more statements to be executed, curly braces are mandatory:

if (true)
{
    Console.WriteLine("Mandatory");
    Console.WriteLine("curly");
    Console.WriteLine("braces");
}

This rule is true for all the constructs in C# language.

The lower than (<) operator is of course just one of the operators you can use for comparison. Below is a full list of the most commonly used comparison operators and their meaning:

  • == (equals)
  • != (not equals)
  • > (greater than)
  • >= (greater than or equal to)
  • < (lower than)
  • <= (lower than or equal to)

Notice that equals has to be typed with double equal signs (==). A single equal sign is used for assigning a value to a variable, property, etc.

The logical condition does not have to be a single comparison. It can be a logical join of any number of logical expressions. The “&&” is used for logical “AND” and “||” is used for logical “OR”.

The following example expands a little bit on the previous bartender example and shows the usage of the equals (==) operator as well as the logical AND (&&) operator:

int customerAge = 17;
bool fakeID = true;

if (customerAge < 18 && fakeID == false)
    Console.WriteLine("Can't serve drinks!");
else
    Console.WriteLine("What can I get you?");

Console.ReadLine();

The if/else statement can be extended by other “else if” statements. The following example is functionally identical to the previous example:

int customerAge = 17;
bool fakeID = true;

if (customerAge > 18)
    Console.WriteLine("What can I get you?");
else if (fakeID)
    Console.WriteLine("What can I get you?");   
else
    Console.WriteLine("Can't serve drinks!");

Console.ReadLine();

For cycle

The “for” cycle will execute whatever it is inside its body for several times. The following example will write numbers from 0 to 9 to the console, each number on a separate line:

for (int number = 0; number < 10; number++)
{
    Console.WriteLine(number);
}

Console.ReadLine();

Looking closer at the example, there are three parts in the “for” cycle parentheses. The first part “int number = 0” is simply a declaration and initialization of a new integer variable called number. The second part ”number < 10” is a logical condition that needs to be met before the “for” body is executed. This condition is checked prior to every repetition of the cycle. If the condition is true the body will be executed again, if not, the code will finish executing the “for” cycle altogether. The third part “number++” is what gets done after the completion of each cycle. In our case the number variable will be increased by 1. The “number++” is identical to writing “number = number + 1”.

Taking all this into consideration, the code will be executed as follows: First a new integer variable called number will be declared and initialized to 0. Then the condition will be checked and because 0 is lower than 10, the code execution will enter the “for” cycle body. This will write the number 0 to the console. Now we are at the end of the “for” cycle and that is the time for the third part of the “for” cycle definition to execute – the number variable will be increased by one. The variable now contains number 1. The “for” cycle now repeats again. First the condition is checked and 1 is still lower than 10. The execution therefore enters the “for” cycle body and the body writes number 1 to the console.

This all continues until a number 9 is written to the console. At the end of that cycle the number variable is again increased by one. This time the new value is 10. Going right to the beginning, the “for” cycle checks the condition. 10 is no longer lower than 10. The “for” cycle therefore ends.

There are two other commands that can be used inside the “for” cycle to influence its execution.

The first is the “continue” command. It will terminate the current “for” cycle execution and return control to the beginning of the cycle. The third part of the “for” cycle definition will still get executed though. In our previous example this would mean that even though we would restart the cycle by using the “continue” command, the variable number would still be increased by one.

The following example shows the usage of the “continue” keyword:

for (int number = 1; number < 10; number++)
{
    if (number < 9)
        continue;

    Console.WriteLine(number);
}

Console.ReadLine();

The output of this code is only the number 9.

The second command is the “break” command. It will terminate the execution of the “for” cycle altogether.

The following example shows the usage of the “break” keyword:

for (int number = 1; number < 10; number++)
{
    if (number == 5)
        break;

    Console.WriteLine(number);
}

Console.ReadLine();

The output of this code are numbers from 1 to 4 – each on a separate line.

While cycle

The “while” cycle will execute whatever it is inside its body for as long as a certain logical condition is true. The following example will continue writing out the “Running” string to the console for a period of five seconds. Then a string “FINISHED” will be written.

DateTime end = DateTime.Now.AddSeconds(5);

while (DateTime.Now < end)
{
    Console.WriteLine ("Running");
}

Console.WriteLine("FINISHED!");

Console.ReadLine();

The “while” cycle can use the “continue” and “break” commands within its body to further influence the execution flow.

Foreach cycle

The “foreach” cycle will execute whatever it is inside its body for each and every child of a specified collection. The collection can be anything that is enumerable, such as an array or a generic list. Again, let us start by an example:

string[] array = new string[] { "One", "Two", "Three" };

foreach (string item in array)
{
    Console.WriteLine(item);
}

Console.ReadLine();

The body of the “foreach” cycle in our example will be executed exactly three times as there are exactly three items inside the array. At the beginning of each cycle the value of the item of the array will be stored in a new string variable called item. This is what we have defined by using the “string item in array” inside the “foreach” parentheses.

The example above will write the following output to the console:

One
Two
Three

The “foreach” cycle can use the “continue” and “break” commands within its body to further influence the execution flow.

Try/catch statement

The “try/catch” statement is a bit different from all of the statements above. It is not driven by any logical condition nor does it repeat the execution of its body for several times. The purpose of the statement is to test for exceptions. Exception is a state the application gets into when it tries to perform something that is not possible or expected.

To give you an example that ends up with an exception, consider creating a new DateTime from numbers that actually cannot represent a real date and time. The following example tries to create a new DateTime from a year number, month number and a day number:

DateTime dateTime = new DateTime(2015, 1, 32);

The day number is obviously wrong and the code will throw an exception. There are many types of exceptions, most of them actually have their own system type. The type of this particular exception is “System.ArgumentOutOfRangeException”. We have in fact specified one of the arguments that was out of range. Every exception also has a message that provides more details. The message of this exception is:„Year, Month, and Day parameters describe an un-representable DateTime.” This gives us a pretty good idea of what went wrong.

Whenever an exception occurs, Visual Studio will enter a debugging mode so you can find out all the information about the exception. If the exception occurs when the program is running in a production environment, it just terminates the program. This is what would be called an unhandled exception.

Working with exceptions in our code is necessary. Sometimes it is even beneficial to throw out our own exceptions. What is important is to handle all of the exceptions we expect to happen and know exactly how to handle. The exception we discussed before could be handled with the use of try/catch statement in the following way:

DateTime dateTime;

try
{
    dateTime = new DateTime(2015, 1, 32);
    Console.WriteLine("Success!");
}

catch
{
    Console.WriteLine("Error!");
}

Console.ReadLine();

Here an exception occurs in the “try” body. Once that happens, the code execution is immediately directed to the “catch” statement and its body is then executed. In our example this would mean that the code execution will never get to the line where “Success!” is written out to the console. Instead, while executing the contents of the “catch” statement, “Error!” will be written out to the console. This way we would manage to inform the user of what went wrong instead of letting the application fail.

If we were to change the example above and specify an existing day for the creation of our DateTime, the code execution would never get to the “catch” statement. It would continue to process other commands in the “try” statement and the “Success!” text would be written out to the console.

To sum this up, whatever causes an exception to be thrown inside the body of the “try” statement, will not terminate the application. Instead, the body of the “catch” statement will get executed and the exception will be considered as handled.

If you need to get access to the exception that caused the program execution flow into the “catch” block, you can have the catch statement declare a new exception variable that you can use to get more details. The following example shows how to write the exception message out to the console:

DateTime dateTime;

try
{
    dateTime = new DateTime(2015, 1, 32);
    Console.WriteLine("Success!");
}

catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

Console.ReadLine();

Sometimes what you need is to catch and handle only a specific type of exception, leaving all other exceptions unhandled. You can specify the type of the exception that you want to handle in the “catch” statement definition. In our following example we are interested only in the “System.ArgumentOutOfRangeException” exception:

DateTime dateTime;

try
{
    dateTime = new DateTime(2015, 1, 32);
    Console.WriteLine("Success!");
}

catch (ArgumentOutOfRangeException)
{
    Console.WriteLine(“Wrong argument!”);
}

Console.ReadLine();

Now only the “System.ArgumentOutOfRangeException” exception will be called by our “catch” statement. All other exceptions will still cause our application to fail.

Notice one another thing in the previous example. If what you need is to only limit the type of exception caught and you are not interested in the exception details itself, you do not need to specify the name of a variable where you want the exception details to be saved.

You can catch more exception types at once. The following example shows how to catch the “System.ArgumentOutOfRangeException” exception as well as any other exception if it is not the “System.ArgumentOutOfRangeException” exception:

DateTime dateTime;

try
{
    dateTime = new DateTime(2015, 1, 32);
    Console.WriteLine("Success!");
}

catch (ArgumentOutOfRangeException)
{
    Console.WriteLine("Wrong argument!");
}

catch (Exception ex)
{
    File.WriteAllText("log.txt", ex.Message);
    throw;
}

Console.ReadLine();

So, again, if the exception is of type “System.ArgumentOutOfRangeException”, the application will notify user that there was a wrong argument. If there is any other exception thrown, it will be caught by the second “catch” statement. The statement will log the exception message into a file and because there is no way the catch statement knows how to manage an unknown and unexpected exception, it chooses to throw it out again. This illustrates one of the most important rules when dealing with exceptions: “Catch and manage all you expect and know how to handle, do not touch the rest.” The reason for this is that somewhere up the code hierarchy there can be another “catch” statement that knows how to handle that specific exception. If we were to swallow that exception (mark it has handled), the try/catch statement somewhere above in the code hierarchy would never get a chance to catch and properly process the exception.

Ternary operator

The ternary operator is a one line construct that behaves similar to an if/else statement. Many times it is preferable to use it instead of an if/else statement due to a better code readability.

Consider the following if statement:

decimal accountBalance = 5000;

string result;

if (accountBalance >= 0)
    result = "You've got money on your account!";
else
    result = "Your account is overdrawn!";

Console.WriteLine(result);

Console.ReadLine();

Now the exactly same thing can be achieved by using a ternary operator:

decimal accountBalance = 5000;

Console.WriteLine(
    accountBalance >= 0 ?
    "You've got money on your account!" :
    "Your account is overdrawn!");

Console.ReadLine();

The ternary operator has three parts. The first part is the logical condition, the second part is the result if the logical condition resolves to true, the third part is the result if the logical condition resolves to false. The first part is divided from the second part by a question mark “?”. The second part is divided from the third part by a colon (:).

Coalesce operator

The coalesce operator is similar to the ternary operator only it is specifically designed to work with NULL values.

Let us look at the following ternary operator:

int? number = 10;

Console.WriteLine(number.HasValue ? number.Value : 0);

Console.ReadLine();

In this example, if the Nullable integer has any value, the value gets written out. If it has no value a 0 is written out. The same functionality can be achieved by using a coalesce operator:

int? number = 10;

Console.WriteLine(number ?? 0);

Console.ReadLine();

The coalesce operator consists of two parts. The first part is a variable that can be NULL but can also have a value. If it has a value the value itself is the result of the coalesce operator. If it does not have a value (the value is NULL), the second part of the coalesce operator will be its result.

Continue to: Methods, classes, objects and organizing everything into files

Go up to: Basics


Should you have any questions or found a mistake that needs correcting, feel free to send an email to: info [at] mycsharp [dot] net


Advertisements :