Description:

This article explores exception handling mechanisms in C#. It describes how C# provides built-in support for handling anomalous situations, known as exceptions, which may occur during the execution of your program. We will start out by understanding exceptions and will see why we need to catch different exceptions.

What is an Exception?

An exception is an error condition or unexpected behavior encountered by an executing program during runtime. In fact the name exception comes from the fact that although a problem can occur; the problem occurs infrequently.

Trapping and handling of runtime errors is one of the most crucial tasks ahead of any programmer. As a developer, you sometimes seem to spend more time checking for errors and handling them than you do on the core logic of the actual program. You can address this issue by using system exceptions that are designed for the purpose of handling errors. In this article, you will learn how to catch and handle exceptions in C#.

Let's see an example where a user enters an input which does not represent a valid number. During the int.Parse method call, the code recognizes this exceptional event and throws a FormatException.

// Example ShowingExceptions
using System;
class ShowingExceptions
{
static void Main()
{
Console.Write("Please enter a number");
string str = Console.ReadLine();
int iNum = int.Parse(str);
Console.WriteLine("You entered {0}. Converted to {1}", str, iNum);
Console.ReadLine();
}
}

Execution :
Please enter a number : Hello

Output:

An unhandled exception of type 'System.FormatException' occurred in mscorlib.dll
Additional information: Input string was not in a correct format.

Now there are various ways of dealing with such problem. The First way is to 'ignore it'. Do not be surprised because that is what most of us tend to do. Though this solution is easy on the programmer, in the bargain, the program looses robustness and is more prone to errors and crashes during execution. The Second solution could be using 'Exception Avoidance'. In this technique, we try to avoid errors beforehand by using 'Condition Checking' wherever possible. One way of 'Condition Checking' could be to read each character in the string, ensuring if it is a digit and then parsing it. 'Exception avoidance' is important at times and should be used when possible, but not always, as it could be more the trouble than it is worth. Can you imagine how tedious it would be to check every letter of every line read in from the keyboard, just to avoid a FormatException and a program crash?

N
ot only is exception avoidance inconvenient at times, but also impossible to use at others. Lets think of a situation where you want to open a file using a StreamReader. If the file you specify does not exist, a FileNotFoundException can occur. But using the Exception Avoidance technique we have discussed so far, you cannot accurately avoid this exception ahead of time and determine that the file exists before trying to read it.

What is Exception Handling and why do we need it?

The mark of a good, robust program is planning for the unexpected, and recovering if it does happen. Errors can happen at almost any time during the compilation or execution of a program. We can detect and deal with these errors using Exception Handling. Exception handling is an in built mechanism in .NET framework to detect and handle run time errors. At the heart of the .NET Framework is the Common Language Runtime (CLR) which in addition to acting as a virtual machine and interpreting and executing IL code on the fly, performs numerous other functions such as type safety checking, memory management, garbage collection and Exception handling. The .NET framework contains lots of standard exceptions. It allows you to define how the system reacts in unexpected situations like 'File not found' , 'Out of Memory' , bad logic, non-availability of operating system resources other than memory, 'Index out of bounds' and so on.

When the code which has a problem, is executed, it 'raises an exception'. If a programmer does not provide a mechanism to handle these anomalies, the .NET run time environment provides a default mechanism, which terminates the program execution. This mechanism is a structured exception handling mechanism.

Exceptions in C#

Exceptions in C# are represented by objects with type names representative of the type of error that occurred in the program. Exceptions in C# provide a structured, uniform, and type-safe way of handling both system level and application level error conditions. . In C#, all exceptions must be represented by an instance of a class type derived from System.Exception. System.Exception class is the base type of all exceptions.An object of an exception is that which describes the exceptional conditions occuring in a code that means, we are catching an exception, creating an object of it, and then throwing it.

Like other modern and structured programming languages, C# also provides a rich mechanism of Exception Handling. Exceptions are handled in C# using the 'try/catch/finally' statements. These keywords are also named as Structured Exception Handling (SEH). The code which 'may cause an exception' is enclosed within a 'try' block as shown below:

try
{
// this code may cause an exception.
}

Your code feels safe now as it has been protected. If an exception does occurs in the code enclosed within the 'try' block, you can handle it. To handle an exception, attach a 'catch' block to the 'try'.

try
{
// this code may cause an exception.
// If it does cause an exception, the execution will not continue.
// Instead,it will jump to the 'catch' block.
}
catch (Exception ex)
{
// I get executed when an exception occurs in the try block.
// Write the error handling code here.
}

Having understood the basic syntax, let's rewrite the example ShowingExceptions

// Example ShowingExceptions using structured exception handling the C# way.

class ShowingExceptions
{
static void main()
{
Console.Write("Please enter a number :");
string str = Console.ReadLine();
double dNo;
}
try
{
dNo =
double.Parse(str);
Console.WriteLine("Parsing successfully without errors");
}
catch(Exception ex)
{
Console.WriteLine("Error : {0} is not a valid number", str);
}

}

Execution :
Please enter a number : Hello

Output:

Error: Hello is not a valid number.

Thus here we notice that when the exception does occur, the program stops executing code from the try block and immediately jumps to the catch block. This is why the output, " Parsing successfully without errors " is not displayed when the exception occurs.

NOTE:

It is not a good idea to display the raw exception message to the user. Instead, show a friendly message to the user and log the actual exception message to some log file for trouble shooting purposes.

Moreover, in the above example, we are handling all types of exceptions. But it is a bad practise to catch all exceptions. You should catch only specific exceptions which are expected in the specific code block. For example, if you are attempting to allocate the memory, you may catch 'System.OutOfMemoryException' and if you are performing mathematical operations, you may catch
'System.DivideByZeroException' exception. Also, you can create and throw custom exceptions.

Eg:

ArgEx ArgumentException = new ArgumentException("You entered bad data");
throw ArgEx;

Ok, But what about the finally block?

C# provides the finally block to enclose a set of statements that need to be executed regardless of the course of control flow. So as a result of normal execution, if the control flow reaches the end of the try block, the statements of the finally block are executed. Moreover, if the control leaves a try block as a result of a throw statement or a jump statement such as break , continue, or goto, the statements of the finally block are executed. The finally block is basically useful in three situations: to avoid duplication of statements, to release resources after an exception has been thrown and to assign a value to an object or display a message that may be useful to the program.

Let's see the example Showing Exceptions again:

// Example ShowingExceptions using finally
class ShowingExceptions
{
static void main()
{
Console.Write("Please enter a number :");
string str = Console.ReadLine();
double dNo;
}
try
{
dNo =
double.Parse(str);
Console.WriteLine("Parsing successfully without errors");
}
finally
{
Console.WriteLine("Storing the number
as 1.0");
dNo = 1.0;
// dNo is assigned the value 1.0 irrespective of an error.
}
}

What are the other Exception Classes?

Here's a list of few Common Exception Classes:

Summary

In this article we saw how Exceptions are handled in C#.Net using the 'try/catch/finally' statements. In the next article, I will describe the advanced situations where we could use exception handling, as well as best practices for Exceptions.