Exception Handling
Introduction
C# and the .NET CLR use exceptions to indicate that an error condition has occurred during program execution. C# programs are under constant threat of running into some kind of trouble. As a program's complexity grows, the possibility that something unusual would happen during its execution also gets higher. Exception handling helps applications trap exceptional events and respond to them in a predictable and robust manner.
11 courses, 8+ hours of training
This chapter shows and explains how to properly handle existing exceptions using try, catch, finally and throw blocks and how to create your own custom exceptions.
What is an Exception?
An Exception is an abnormal event or error condition existing in the technical execution of a particular statement that occurs during program execution. Exceptions can occur in the code you write (internal) or in an external code (DLL) that your program calls. Examples of error conditions include the following:
- Network communication problems
- Element access that is beyond the bound of an array
- Running out of memory during program execution
- Division by zero
An Exception Example
A common exception occurs when an integer is divided by zero, which then triggers an unhandled divide-by-zero exception as follows:
C# code
[c language="#"]
using System;
namespace ExceptionHandling
{
class Program
{
static void Main(string[] args)
{
int x, y,Result;
x = 10;
y = 0; Unprotected block
Result = x / y; //exception occur
Console.WriteLine(Result);
}
}
}
Now place code that you think is likely to raise an exception in the try block, where it is protected from exceptions. Exceptions raised in the try block are trapped and the catch statements handle the exception, which consists of a catch filter (DivideByZeroException). After the exception is handled, the execution continues at the first statement after the catch statement:
C# code
[caption id="attachment_17109" align="alignnone" width="616"] Click to view larger image[/caption]
CLR Exception Handling Mechanism
When an exception occurs in a program, the .NET framework runtime handles the problem by creating an exception object, populating it with information related to the error and passing it on to any fault handling code. C# does not force you to use try/catch blocks. The .NET runtime will try its best to search for a particular fault handler from the method call stack for an exception thrown in an unprotected block. If none is found, the .NET runtime generates an UnhandledExceptions event.
Exception Class Hierarchy
Using Try/Catch Blocks
To catch and handle exceptions, you need to place exception-throwing code in a try code. Then, you catch the resulting exception when it gets thrown in one or more catch blocks where error handling code is placed to properly deal with and recover from the exception. Optionally, you can add a finally block, whose code will always be executed regardless of whether or not an exception is thrown.
C# code
[c language="#"]class Program
{
static void Main(string[] args)
{
try
{
x[0] = 10;
//SUSPECTED CODE
for (int i = 0; i {
Console.WriteLine(x[i]);
}
}
catch (IndexOutOfRangeException err) // Exception handling
{
Console.WriteLine(err.Message);
}
Console.ReadKey();
}
}
In this program, we declare an array x of integer type with size 2, assign the values 10 and 20 to each array element, and display these values by using for loop. The for loop starts from 0 and is executed thrice due to the equal sign in the condition. However, the array size is 2 only and since the loop is executed three times, .Net runtime immediately throws an IndexOutOfRange error which is filter and handled by a catch block. The program output displays this error message:
Figure 1.1: Index Out of Range Error
NOTE: if you don't mention a specific error, for instance IndexOutOfRange, and mention only Default Exception class in the catch block, then .NET runtime handles this by filtering it to an out of index error as follows:
C# code
[c language="#"] Try
{
….
}
catch (Exception err) // Exception handling
{
Console.WriteLine(err.Message);
}
Using Multiple Catch Blocks
If your code can potentially throw several types of exceptions, you can add multiple catch blocks, one for each exception type. When using multiple catch blocks, it will catch the most specific exceptions first and catch the most general exceptions last.
C# code
[c language="#"]public static void Main(string[] args)
{
try
{
int total = 0;
for (int i = 0; i < args.Length; i++)
{
}
Console.WriteLine("you entered {0} arguments and their sum is {1} ",args.Length,total);
}
// Exception Handling
catch (FormatException)
{
Console.WriteLine("Can't convert to Integer");
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Command Line Arguments is Not Entered");
}
catch (Exception)
{
Console.WriteLine("Unknown Error");
}
Console.ReadLine();
}
This program has multiple catch blocks. It converts command-line arguments to integers, adds them, and prints the sum to the console.
Figure 1.2: Multiple catch statements
Using a Finally Block
In certain programming circumstances, you will want to ensure that a certain piece of code is executed in all cases regardless of whether or not an exception is thrown. A finally block is used for just this purpose.
C# code
[c language="#"]public static void Main(string[] args)
{
try
{
if (args.Length > 0)
{
Console.WriteLine(args[0]);
}
}
// Exception Handling
catch (IndexOutOfRangeException)
{
Console.WriteLine("Index out of Range");
finally
{
Console.WriteLine("Thank you for Using Exception Handling!");
}
Console.ReadLine();
}
When you compile this program, no matter what happens when the program runs, the "Thank you…" message gets printed to the console:
Figure 1.3: Finally block
Custom Exception class
In most cases, .NET's built-in exception classes, combined with a custom message, should meet your exception handling requirements. However, in some cases, you might need exception types that are specific to the problem you are solving. Microsoft recommends that you consider the following when you design a custom exception class:
- Create an exception class only if no exception class exists that satisfies your requirement.
- Derive all custom exception classes from the ApplicationException or Exception class.
-
Implement these constructors with the signature shown as:
C# code
{
// The constructor that takes msg as a parameter
public NumberZeroExceptionMagic(string msg) : base(msg) { }
}
The following example divides two integer type numbers, but if we divide the denominator by zero,.NET runtime throws a DivideByZeroException. This situation can also be handled by a Custom Exception class as follows:
C# code
[c language="#"]public class NumberZeroExceptionMagic : ApplicationException
{
public NumberZeroExceptionMagic() : base() { }
// The constructor that takes msg as a parameter
public NumberZeroExceptionMagic(string msg) : base(msg) { }
public class Test
{
static void Main(string[] args)
// Prompt the user to enter an integer
Console.WriteLine("Please input an integer: ");
// Try this block of code
try
{
int Numerator = 10;
// Store the input in x
// If the number entered is 0...
if (x == 0)
{
// ...throw our custom exception with the following message parameter
throw new NumberZeroExceptionMagic("You are not allowed to enter number 0");
Console.WriteLine("Division: " + (Numerator/x).ToString());
}
catch (NumberZeroExceptionMagic e)
{
// And display the error message
Console.WriteLine("Exception: " + e.Message);
Console.ReadLine();
}
}
This program takes the input for denominator from the user. When the user enters any number except zero, the program shows the desired output, but in case the user enters zero, the exception is thrown by the custom exception class:
11 courses, 8+ hours of training
Figure 1.4: Custom Exception class