Exceptions in C# provide a structured, and type-safe way of handling both system level and application level error conditions. The exception mechanism in C# is very similar to that of C++, with a few important differences.
In C#, all exceptions must be represented by an instance of a class type derived from System.Exception
Causes of exceptions:
- Certain exceptional conditions that arise during the processing of C# statements and expression cause an exception in certain circumstances when the operation cannot be completed normally. For example, an integer division operation throws a System.DivideByZeroException if the denominator is zero.
- A throw statement throws an exception immediately and unconditionally. Control never reaches the statement immediately following the throw.
Handling Exceptions:
Consider the following code:
List 1: Test1.cs
using System;
class Test
{
public static void Main(string[] args)
{
int i = 10/Int32.Parse(args[0]);
Console.WriteLine(i);
}
}
Now when we run the above program like
test 5
It will print 2 on console.
But suppose if we run it like
test or test hello
Then in that case program will crash. We need to handle these situations by modifying our code.
Exceptions are handled by try-catch statement.
List 2: Test2.cs
using System;
class Test
{
public static void Main(string[] args)
{
try
{
int i = 10/Int32.Parse(args[0]);
Console.WriteLine(i);
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
Now, when we run above program, there will be many possibilities.
Scenario 1:
we run it like test 5. output will be 2. so if try block is executed smoothly, catch block will never execute.
Scenario 2:
We run it like test. In this case output will be a string "An exception of type System.IndexOutOfRangeException was thrown". This output is coming from catch block. Thus if there is any runtime problem with the try block, control will be transferred to the catch block and no further statements in try block will be executed.
Scenario 3:
We run it like test hello. In this case output will be a string "The input string is not in correct format."
Scenario 4:
We run it like test 0. In this case output will be a string "Attempt to divide by zero"
Scenario 5:
We run it like test 1212121212121212. In this case output will be a string
"Value was either too large or too small for an Int32".
So, there are four situations need to be handled.
Consider the following code:
List 3: test3.cs
using System;
class Test3
{
public static void Main(string[] args)
{
try
{
int i = 10/Int32.Parse(args[0]);
}
catch(IndexOutOfRangeException e)
{
Console.WriteLine(e.Message);
}
catch(FormatException e)
{
Console.WriteLine(e.Message);
}
catch(DivideByZeroException e)
{
Console.WriteLine(e.Message);
}
catch(OverflowException e)
{
Console.WriteLine(e.Message);
}
}
Four catch blocks are included in this code. To make the program simple enough, all the catch blocks content is kept same. So depending upon the runtime situation, appropriate catch block will be executed.
Consider the following code:
List 4: Test4.cs
using System;
class Test
{
public static void Main(string[] args)
{
try
{
int i = 10/Int32.Parse(args[0]);
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
Console.WriteLine("This is finally block");
}
}
}
This is the example of try-catch-finally block. The execution will be either entire try block and then finally block, or exception in try block-catch block-finally block. Thus finally block will execute even if exception occurs or not.
Common Exception Classes:
The following exceptions are thrown by certain C# operations.
System.OutOfMemoryException |
Thrown when an attempt to allocate memory (via new) fails. |
System.OutOfMemoryException |
Thrown when the execution stack is exhausted by having too many pending method calls; typically indicative of very deep or unbounded recursion. |
System.NullReferenceException |
Thrown when a null reference is used in a way that causes the referenced object to be required. |
System.TypeInitializationException |
Thrown when a static constructor throws an exception, and no catch clauses exists to catch in. |
System.InvalidCastException |
Thrown when an explicit conversion from a base type or interface to a derived types fails at run time. |
System.ArrayTypeMismatchException |
Thrown when a store into an array fails because the actual type of the stored element is incompatible with the actual type of the array. |
System.IndexOutOfRangeException |
Thrown when an attempt to index an array via an index that is less than zero or outside the bounds of the array. |
System.MulticastNotSupportedException |
Thrown when an attempt to combine two non-null delegates fails, because the delegate type does not have a void return type. |
System.ArithmeticException |
A base class for exceptions that occur during arithmetic operations, such as DivideByZeroException and OverflowException. |
System.DivideByZeroException |
Thrown when an attempt to divide an integral value by zero occurs. |
System.OverflowException |
Thrown when an arithmetic operation in a checked context overflows. |