Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Week 7 - Exceptions

Table of contents

Do the Practical


In this topic, we will learn about exceptions in C#. An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions.

Exception Basics

Throwing an Exception

Click to show/hide explanation

To throw an exception, the throw keyword is used. The throw keyword is followed by an exception object. The exception object is created using the new keyword and the name of the exception class. The exception object is then passed to the throw keyword.

throw new Exception("An exception has occurred");

Catching an Exception

Click to show/hide explanation

To catch an exception, the try and catch keywords are used. The try keyword is followed by a block of code that may throw an exception. The catch keyword is followed by a block of code that will be executed if an exception is thrown. The catch keyword is followed by the name of the exception class that will be caught. The catch block can be followed by a finally block, which will always be executed regardless of whether an exception is thrown.

try
{
    // Code that may throw an exception
}
catch (Exception e)
{
    // Code that will be executed if an exception is thrown
}
finally
{
    // Code that will always be executed
}

Common Exceptions

Exception Class Description
ArgumentException Raiused when a non-null argument that is passed to a method is invalid
ArgumentNullException Raised when a null argument is passed to a method
ArgumentOutOfRangeException Raised when the value of a an argument is outside the range of valid values
DivideByZeroException Raised when an integer value is divide by zero
FileNotFoundException Raised when a physical file does not exist at the specified location
IndexOutOfRangeException Raised when an array index is outside the lower or upper bound of an array or collection.
InvalidOperationException RaisedWhen the specified key for accessing a member in a collection does not exist.
NotSupportedException Raised when a method or operation is not supported
NullReferenceException Raised when the program access members of null object
OverflowException Raised when an arithmetic, casting or conversion operation results in an overflow
OutOfMemoryException Raised when a program does not get enough memory to execute the code
StackOverflowException Raised when the program does not get enough memory to execute the code
TimeoutException Raised when the time interval allotted to an operation has expired
NotImplementedException Raised when a method or property has not been implemented

A Detailed Example

Click to show/hide explanation

Consider the implimentation of a bank account class. The bank account class has a Balance property that contains the current balance of the account. The Withdraw method is used to withdraw money from the account, the Deposit method is used to deposit money into the account, and the Transfer method is used to transfer money from one account to another.

The BadBankAccount class below does not handle the exceptional cases of withdrawing more money than is in the account or transferring more money than is in the account, leading to the balance of the account becoming negative.

THIS IS A BAD EXAMPLE. DO NOT USE THIS CODE IN YOUR PROGRAMS.

public class Program
{
    public static void Main()
    {
        // Bug: Account balance can become negative
        BadBankAccount account1 = new BadBankAccount(-100);
        BadBankAccount account2 = new BadBankAccount(100);

        // Bug: Withdraw more money than is in the account
        account1.Withdraw(200);
        Console.WriteLine(account1.Balance); // -300

        // Bug: Transfer more money than is in the account
        account1.Transfer(account2, 200);
        Console.WriteLine(account1.Balance); // -500

        // Bug: Withdraw negative money (making money out of thin air)
        account1.Withdraw(-100);
        Console.WriteLine(account1.Balance); // -200

        // Bug: Negative transfer (stealing money, basically...)
        account2.Transfer(account1, -1000);
        Console.WriteLine(account1.Balance); // 500
    }
}

public class BadBankAccount {
    public double Balance { get; private set; }
    public BadBankAccount(double balance) {
        Balance = balance;
    }

    public void Withdraw(double amount) {
        Balance -= amount;
    }

    public void Deposit(double amount) {
        Balance += amount;
    }

    public void Transfer(BadBankAccount other, double amount) {
        Withdraw(amount);
        other.Deposit(amount);
    }
}

The GoodBankAccount class below handles the exceptional cases of withdrawing more money than is in the account or transferring more money than is in the account, by throwing an exception.

public class Program
{
    public static void Main()
    {
        GoodBankAccount account1, account2;
        
        // Cannot create account with negative balance
        try
        {
            account1 = new GoodBankAccount(-100); // Exception: Cannot create account with negative balance
            account2 = new GoodBankAccount(100); // This line will not be executed
        }
        catch (ArgumentException e)
        {
            Console.WriteLine(e.Message); // Cannot create account with negative balance
            account1 = new GoodBankAccount(100);
            account2 = new GoodBankAccount(100);
            return;
        }

        // Cannot overdraw account
        try
        {
            for (int i = 0; i < 3; i++){
                account1.Withdraw(50); // Throws exception on third iteration
                Console.WriteLine(account1.Balance); // 50, 0
            }
        }
        catch (ArgumentException e)
        {
            Console.WriteLine(e.Message); // Insufficient funds
        }

        // Cannot transfer more money than is in the account
        try
        {
            account1.Transfer(account2, 200); // Exception: Insufficient funds
            Console.WriteLine(account1.Balance); // This line will not be executed
        }
        catch (ArgumentException e)
        {
            Console.WriteLine(e.Message); // Insufficient funds
        }

        // Cannot withdraw negative amount
        try
        {
            account1.Withdraw(-100); // Exception: Cannot withdraw negative amount
            Console.WriteLine(account1.Balance); // This line will not be executed
        }
        catch (ArgumentException e)
        {
            Console.WriteLine(e.Message); // Cannot withdraw negative amount
        }

        // Cannot transfer negative amount
        try
        {
            account2.Transfer(account1, -100); // Exception: Cannot transfer negative amount
            Console.WriteLine(account1.Balance); // This line will not be executed
        }
        catch (ArgumentException e)
        {
            Console.WriteLine(e.Message); // Cannot transfer negative amount
        }

        // Display final balances
        Console.WriteLine(account1.Balance); // 0
        Console.WriteLine(account2.Balance); // 100
    }
}

public class GoodBankAccount {
    public double Balance { get; private set; }
    public GoodBankAccount(double balance) {
        if (balance < 0)
        {
            throw new ArgumentException("Cannot create account with negative balance");
        }
        Balance = balance;
    }

    public void Withdraw(double amount) {
        if (amount < 0)
        {
            throw new ArgumentException("Cannot withdraw negative amount");
        }
        if (amount > Balance)
        {
            throw new ArgumentException("Insufficient funds");
        }
        Balance -= amount;
    }

    public void Deposit(double amount) {
        if (amount < 0)
        {
            throw new ArgumentException("Cannot deposit negative amount");
        }
        Balance += amount;
    }

    public void Transfer(GoodBankAccount other, double amount) {
        if (amount < 0)
        {
            throw new ArgumentException("Cannot transfer negative amount");
        }
        if (amount > Balance)
        {
            throw new ArgumentException("Insufficient funds");
        }
        Withdraw(amount);
        other.Deposit(amount);
    }
}