Exception Handling in C#

An exception is an erroneous situation that occurs during program execution. Exceptional situation arise when an operation cannot be completed normally. When an exception occurs in an application, the system throws an error. The error is handled through the process of exception handling.

C# provides built-in support for handling anomalous situations, known as exceptions, which may occur during the execution of your program. These exceptions are handled by code that is outside the normal flow of control.

 

Exception handling is a way to handle errors at runtime that cause application termination.

 

.NET supports structured exception handling with the help of try, catch, finally and throw key words.

 

C# provides following keywords to handle an exception. 

  • Try
  • Catch
  • Finally

The try block

 

The code, which seems to generate an exception, is placed under the try block. When an exception occurs in the try section, code compilation is transferred to the catch section.

 

try

{

//Code that may cause an exception

}

 

A try block should have at least one catch or finally block. We can use both catch and finally block after the try block.

 

Remember there should be no other code between these blocks.

 

In the above code if no errors or errors are found, the flow of execution goes to the third block finally. If an exception is thrown execution goes to a catch block.

 

Exception Nesting

 

You can create an exception inside of another. This is referred to as nesting an exception.

 

To nest an exception, write a try block in the body of the parent exception. The nested try block must be followed by its own catch(es) clause.

 

The catch block

 

In this block you implement methods for dealing with any possible errors of the try block. At the end of this block execution continues to the last code block.

 

When an exception occurs in the try section, code compilation is transferred to the catch block.

 

try

{

//Code that may cause an exception

}

catch (...)

{

//Code for handling errors

}

 

The catch block should be immediately placed after try block.

 

The following program shows the catch block:

 

using System;

namespace exception_example1

{

    class Program

    {

        static void Main(string[] args)

        {

            try

            {

                int i, k = 0, j;

                Console.Write("Enter a number one: ");

                i = Convert.ToInt32(Console.ReadLine());

                Console.Write("Enter a number two: ");

                j = Convert.ToInt32(Console.ReadLine());

                k = i / j;

                Console.WriteLine("Output of division : {0}", k);

                Console.ReadKey();

            }

 

            catch (DivideByZeroException ex)

            {

                Console.WriteLine(ex.Message);

                Console.ReadKey();

            }

        }

    }

}

 

In the above program if you input the second number as zero (0) it will generate DivideByZeroException.

 

The catch statement of the catch block takes an object of the exception class as a parameter, which refers to the raised exception. When the exception is caught, the statements within the catch blocks are executed.

 

One of the properties of the Exception class is called Message. This property contains a string that describes the type of error that occurred. You can then access this Exception.Message property to display an error message if you want.

 

You can have multiple catch blocks after the try block. See the code below:

 

using System;

 

namespace exceptionHandling_example3

{

    class Program

    {

        static void Main(string[] args)

        {

            double Operand1, Operand2;

            double Result = 0.00;

            char Operator;

 

            Console.WriteLine("This program allows you to perform an operation on two numbers");

 

            try

            {

                Console.Write("Enter a number: ");

                Operand1 = double.Parse(Console.ReadLine());

                Console.Write("Enter an operator: ");

                Operator = char.Parse(Console.ReadLine());

                Console.Write("Enter a number: ");

                Operand2 = double.Parse(Console.ReadLine());

 

                if (Operator != '+' &&

                    Operator != '-' &&

                    Operator != '*' &&

                    Operator != '/')

                    throw new Exception(Operator.ToString());

 

                if (Operator == '/') if (Operand2 == 0)

                        throw new DivideByZeroException("Division by zero is not allowed");

 

                switch (Operator)

                {

                    case '+':

                        Result = Operand1 + Operand2;

                        break;

 

                    case '-':

                        Result = Operand1 - Operand2;

                        break;

 

                    case '*':

                        Result = Operand1 * Operand2;

                        break;

 

                    case '/':

                        Result = Operand1 / Operand2;

                        break;

 

                    default:

                        Console.WriteLine("Bad Operation");

                        break;

                }

                Console.WriteLine("\n{0} {1} {2} = {3}", Operand1, Operator, Operand2, Result);

            }

            catch (DivideByZeroException ex)

            {

                Console.WriteLine(ex.Message);

            }

            catch (Exception ex)

            {

                Console.WriteLine("\nOperation Error: {0} is not a valid operator", ex.Message);

            }

            Console.ReadKey();

        }

    }

}

 

The finally block

 

The finally block is executed whether or not an exception was thrown.

 

try

{

//Code that may cause an exception

}

catch (...)

{

//Code for handling exception

}

finally

{

//clean up code

}

 

The catch block is used to handle exceptions that occur in a try block. The finally block is used to guarantee the execution of statements, regardless of whether an exception has occurred or not.

 

See the code to understand finally block

 

using System;

namespace exception_example1

{

    class Program

    {

        static void Main(string[] args)

        {

            int i, k = 0, j;

            try

            {

                Console.Write("Enter a number one: ");

                i = Convert.ToInt32(Console.ReadLine());

                Console.Write("Enter a number two: ");

                j = Convert.ToInt32(Console.ReadLine());

                k = i / j;

            }

 

            catch (DivideByZeroException ex)

            {

                Console.WriteLine(ex.Message);

                Console.ReadKey();

            }

 

            finally

            {

                Console.WriteLine("Output of division : {0}", k);

                Console.ReadKey();

            }

        }

    }

}

 

Points about finally block 

  • You can have only one finally block for each try block.
  • It is not mandatory to have a finally block after a try block.
  • The finally block is used to do all the clean up code.
  • It does not support the error message, but all the code contained in the finally block is executed after the exception is raised.

To cover unmanaged resource we use finally block. For example when we are not able to find file/database exception we close the file.

 

It is used for cleaning up resources that your program might have used and generic code that should always be executed.

 

Exceptions and Custom Messages

 

Sometimes, the message provided by the Exception class may not be clear to the normal users. As an alternative, you can create your own message and display it to the user.

 

You can display the exception message along with the user defined custom message. See the program below.

 

using System;

 

namespace exceptionHandeling_Example2

{

    class Program

    {

        static void Main(string[] args)

        {

            int num1, num2, sum;

 

            try

            {

                Console.Write("Enter first number : ");

                num1 = int.Parse(Console.ReadLine());

                Console.Write("Enter second number : ");

                num2 = int.Parse(Console.ReadLine());

                sum = num1 + num2;

                Console.WriteLine(sum);

            }

            catch (Exception e)

            {

                Console.WriteLine(e.Message);

                Console.WriteLine("The error indicates that the input was not provided" +

                "in the desired format, You might have provide input not as integer");

            }

            Console.ReadKey();

        }

    }

}

 

Throwing an Exception

 

Exceptions can be explicitly generated by a program using the throw keyword.

 

Exceptions are used to indicate that an error has occurred while running the program. Exception objects that describe an error are created and then thrown with the throw keyword. The runtime then searches for the most compatible exception handler.

 

using System;

namespace exceptionHandling_example4

{

    class Program

    {

        static void Main(string[] args)

        {

            int total = 0;

            int[] arr = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

 

            try

            {

 

                for (int i = 0; i <= 10; i++)

                {

                    total += arr[i];

 

                }

                throw new System.Exception();

            }

                catch(Exception ex)

            {

                    Console.WriteLine("Unknown error");

                    Console.ReadLine();

                }

            }

        }

    }

 

We should not throw exception as it is not good practice of programing. We should try to handle it in a more better manner.

 

I will be explaining more about exception handling and how to throw exception in my coming articles.

 

The Exception Class

 

To support exception handling, the .NET Framework provides a special class called Exception. Once the compiler encounters an error, the Exception class allows you to identify the type of error and take an appropriate action.

 

Normally, Exception mostly serves as the general class of exceptions. Anticipating various types of problems that can occur in a program, Microsoft derived various classes from Exception to make this issue friendlier.

 

As a result, almost any type of exception you may encounter already has a class created to deal with it. Therefore, when your program faces an exception, you can easily identify the type of error.

 

Exceptions are of two types:  

  • SystemException
  • ApplicationException

There are many exception classes, which are directly or indirectly derived from the System.Exception class. Some of the exception classes derived from the System.Exception class are System.System.Exception and System.ApplicationException.

  

The Hierarchy of Exception Class

 

exception.gif
 

SystemException: These exceptions are defined and the common language runtime throws SystemException. The System.System.Exception acts as a base class for all predefined exception.

 

ApplicationException:  These exceptions are not defined. The ApplicationException is thrown by a user program rather than the runtime. They are non-fatal error. If any user-defined application requires its own exception, it should inherit the exception from the System.ApplicationException class.

Following are some common exception classes.

Exception Class

Causes

SystemException

A failed run-time checks; used as a base class for other.

AccessException

Failure to access a type member, such as a method or field.

ArgumentException

An argument to a method was invalid.

ArgumentNullException

A null argument was passed to a method that doesn't accept it.

ArgumentOutOfRangeException

Argument value is out of range.

ArithmeticException

Arithmetic over - or underflow has occurred.

ArrayTypeMismatchException

Attempt to store the wrong type of object in an array.

BadImageFormatException

Image is in the wrong format.

CoreException

Base class for exceptions thrown by the runtime.

DivideByZeroException

 An attempt was made to divide by zero.

FormatException

The format of an argument is wrong.

IndexOutOfRangeException

An array index is out of bounds.

InvalidCastExpression

An attempt was made to cast to an invalid class.

InvalidOperationException

A method was called at an invalid time.

MissingMemberException

An invalid version of a DLL was accessed.

NotFiniteNumberException

A number is not valid.

NotSupportedException

Indicates that a class does not implement a method.

NullReferenceException

Attempt to use an unassigned reference.

OutOfMemoryException

Not enough memory to continue execution.

StackOverflowException

A stack has overflown.

Conclusion

By now, you should have a good understanding of exception handling and their usage. Your feedback and constructive contributions are welcome.  Please feel free to contact me for feedback or comments you may have about this article.

Up Next
    Ebook Download
    View all
    Learn
    View all