Exceptions In C#

System.Exception is the base class for all other exceptions. Below this level are the System.ApplicationException and System.SystemException classes which are derived from the System.Exception class.
 
img
 
The SystemException class acts as the base class for all the pre-defined Exceptions. ApplicationException class is to be used for any custom exceptions that you are to create in your application. Unlike the System Exceptions, these are forwarded by the application and not the CLR.
 
Below is a table listing some of the classes dervied from SystemException class.
 

Exception Class

Description

System.IO.IOException Handles Input/Output errors
System.IndexOutOfRangeException Handles errors generated when a method refers to an array element, which is out of its bound.
System.NullReferenceException Hanldes errors generated during the process of dereferencing a null object.
System.DivideByZeroException Handles errors generated during the process of dividing a number by zero.
InvalidCastException Handles errors generated during typecasting.
OutOfMemoryException Handles memory allocation to the application errors.
 
Handling Exceptions
 
Exceptions are handled by using exception handlers. These exception handlers divide the code in blocks.
 
The try Block
 
All the codes that have a chance of throwing exceptions are put inside the Try block. Given below is a simple try block code.
 
try
{
    //Statements that may throw exceptions.
}
 
The catch Block
 
If any statement inside the try block throws an exception, the execution control is passed onto the appropriate catch block. This allows the application to recover from exceptions. Catch block follows the following syntax:-
 
catch (…)
{
 	//Error Handling Code
}
 
Note: Every try block must have an associated catch block and vice versa.
 
The following code would trap the exception thrown in the previous example.
 
try
{
    float Result = I / J;
}
catch
{
    Console.WriteLine("An error occured while trying to compute the result");
}
 
Whenever the user enters a value of 0 for J, an exception would be thrown. Since, this code is contained in a try block, the code inside the catch block will be executed and a message “An error occured while trying to compute the result” will be shown to the user.
 
In the above example, the type of exception being thrown is unknown. So, no matter what exception is thrown, the same message will be displayed.
 
You can specify the type of exception a catch block handles in the following way:-
 
try
{
    Result = Convert.ToInt32(I / J);
}
catch (DivideByZeroException)
{
    Console.WriteLine("You tried to divide the number by zero");
}
 
The catch block declaration can also instantiate an object of the corresponding Exception class providing access to exception specific information – Error Codes, Description, etc.
 
try
{
    Result = Convert.ToInt32(I / J);
}
catch (DivideByZeroException ex)
{
    Console.WriteLine(ex.Message);
}
 
The code given below is a modified form of the earlier example.
 
Console.WriteLine("Enter Two Numbers:-");
int I = Convert.ToInt32(Console.ReadLine());
double J = Convert.ToDouble(Console.ReadLine());
int Result = 0;
try
{
    Result = Convert.ToInt32(I / J);
}
catch
{
    Console.WriteLine("An error occured while trying to compute the result");
}
Console.WriteLine("The result is {0}", Result);
Console.Read();
 
‘Result’ can now generate two types of exception: DivieByZeroException and OverflowException. When the user enters a very high value, say 65536275 for the variable I and an extremely low value, say 0.0000001 for J.
 
The result would exceed the range of the int datatype and the OverflowException would be thrown. Because the user would be treated with the same error message, he/she might not be able to determine the exact cause of the error.
 
This is where the catch block comes in handy. Multiple catch blocks can be attached to a try block. Each of them should differ in the type of exception they handle.
 
Console.WriteLine("Enter Two Numbers:-");
int I = Convert.ToInt32(Console.ReadLine());
double J = Convert.ToDouble(Console.ReadLine());
int Result = 0;
try
{
    Result = Convert.ToInt32(I / J);
}
catch (DivideByZeroException)
{
 
    Console.WriteLine("You tried to divide the number by zero");
}
catch (OverflowException)
{
    Console.WriteLine("The operation resulted in an overflow");
}
catch(Exception)
{
    Console.WriteLine("An error occured while trying to compute the result");
}
Console.WriteLine("The result is {0}", Result);
Console.Read();
 
Now, if an OverflowException is thrown, the message “The operation resulted in an overflow” will be displayed. For the DivideByZero exception, the message “You tried to divide the number by zero” will be shown. For any other exception, the last message “An error occured while trying to compute the result” will be displayed.
 
Order of Catch Blocks
 
int A = 5, B = 0;
try
{
    A = A / B;
}
catch (Exception ex)
{
    Console.Write("Exception");
}
catch (DivideByZeroException ex)
{
    Console.Write("Divide By Zero Exception");
}
 
The order of the catch block is very important. A series of catch statements needs to be in decreasing order of derivation. For example, the most derived objects must appear first.
 
The above code generates the following compile-error: “A previous catch clause already catches all exceptions of this or of a super type (’System.Exception’)”.
 
If the catch(Exception) block is declared at the top, even a DivideByZeroException or the OverflowException will be handled by this block. This is because both of them are indirectly derived from the Exception class. Infact, C# does not allow such scenarios. So, you must first declare the exception class that is at a deeper level of the hierarchy.
 
The correct code would be as follows:-
 
int A = 5, B = 0;
try
{
    A = A / B;
}
catch (DivideByZeroException ex)
{
    Console.Write("Divide By Zero Exception");
}
catch (Exception ex)
{
    Console.Write("Exception");
}
 
The finally block
 
This block is used to execute statements which are to be executed regardless of whether the exception is thrown or not. This may include a code such as to close a file, an existing SQL connection, etc. Only one finally block can exist for a try block. Also, the finally block is optional.
 
One may argue that why we need the finally block because all statements below the entire try – catch block will be executed, irrespective of whether an exception is thrown or not. However, the code in the finally block is executed, even if a return statement is encountered inside the try or the catch block. The same is not true for the codes following the try – catch block.
 
int I = 10, J = 0;
 
float Result = 0;
try
{
    Result = I / J;
}
catch
{
    Console.WriteLine("An error occured while trying to compute the result");
    return;
}
Console.WriteLine("The result is {0}", Result);
Console.Read();
 
The output of the preceeding block of code would be:-
 
An error occured while trying to compute the result
 
int I = 10, J = 0;
 
float Result = 0;
try
{
    Result = I / J;
}
catch
{
    Console.WriteLine("An error occured while trying to compute the result");
    return;
}
finally
{
    Console.WriteLine("The result is {0}", Result);
    Console.Read();
}
 
While, the output for this would be:-
 
An error occured while trying to compute the result The result is 0
 
To Download Exceptions Handling example Click here.
 
To view downloaded examples, Please Ensure that .NET Framework is installed on your system.